Skip to content

Instantly share code, notes, and snippets.

@and1truong
Created August 14, 2012 04:01
Show Gist options
  • Select an option

  • Save and1truong/3346169 to your computer and use it in GitHub Desktop.

Select an option

Save and1truong/3346169 to your computer and use it in GitHub Desktop.
diff -Naur nohack/sites/all/modules/ubercart/payment/uc_payment/uc_payment.module_11_07_2012 dev/sites/all/modules/ubercart/payment/uc_payment/uc_payment.module_11_07_2012
--- nohack/sites/all/modules/ubercart/payment/uc_payment/uc_payment.module_11_07_2012 1970-01-01 07:00:00.000000000 +0700
+++ dev/sites/all/modules/ubercart/payment/uc_payment/uc_payment.module_11_07_2012 2012-05-15 06:54:07.000000000 +0700
@@ -0,0 +1,828 @@
+<?php
+
+/**
+ * @file
+ * Defines the payment API that lets payment modules interact with Ubercart.
+ *
+ * The payment system in Ubercart relies on hooks to let the main program know
+ * what payment modules are installed and what their current settings are. The
+ * customer can choose a payment type at checkout, and the proper information
+ * will be collected to complete the purchase.
+ */
+
+require_once('uc_payment_checkout_pane.inc');
+require_once('uc_payment_order_pane.inc');
+require_once('uc_payment.ca.inc');
+
+/*******************************************************************************
+ * Hook Functions (Drupal)
+ ******************************************************************************/
+
+/**
+ * Implements hook_menu().
+ */
+function uc_payment_menu() {
+ $items['admin/store/settings/payment'] = array(
+ 'title' => 'Payment settings',
+ 'description' => 'Configure the payment settings.',
+ 'page callback' => 'uc_payment_settings_overview',
+ 'access arguments' => array('administer store'),
+ 'file' => 'uc_payment.admin.inc',
+ );
+ $items['admin/store/settings/payment/overview'] = array(
+ 'title' => 'Overview',
+ 'description' => 'View the payment settings.',
+ 'access arguments' => array('administer store'),
+ 'weight' => -10,
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ );
+ $items['admin/store/settings/payment/edit'] = array(
+ 'title' => 'Edit',
+ 'description' => 'Edit the payment settings.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_payment_settings_form'),
+ 'access arguments' => array('administer store'),
+ 'weight' => -5,
+ 'type' => MENU_LOCAL_TASK,
+ 'file' => 'uc_payment.admin.inc',
+ );
+ $items['admin/store/settings/payment/edit/basic'] = array(
+ 'title' => 'Payment settings',
+ 'description' => 'Edit the basic payment settings.',
+ 'access arguments' => array('administer store'),
+ 'weight' => -10,
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ );
+ $items['admin/store/settings/payment/edit/methods'] = array(
+ 'title' => 'Payment methods',
+ 'description' => 'Edit the payment method settings.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_payment_methods_form'),
+ 'access arguments' => array('administer store'),
+ 'weight' => -5,
+ 'type' => MENU_LOCAL_TASK,
+ 'file' => 'uc_payment.admin.inc',
+ );
+ $items['admin/store/settings/payment/edit/gateways'] = array(
+ 'title' => 'Payment gateways',
+ 'description' => 'Edit the payment gateway settings.',
+ 'access arguments' => array('administer store'),
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_payment_gateways_form'),
+ 'weight' => 0,
+ 'type' => MENU_LOCAL_TASK,
+ 'file' => 'uc_payment.admin.inc',
+ );
+
+ $items['cart/checkout/line_items'] = array(
+ 'title' => 'Return order totals',
+ 'page callback' => 'uc_payment_get_totals',
+ 'access arguments' => array('access content'),
+ 'type' => MENU_CALLBACK,
+ );
+ $items['cart/checkout/payment_details/%'] = array(
+ 'title' => 'Payment details',
+ 'description' => 'Add the payment details to the checkout pane.',
+ 'page callback' => 'uc_payment_get_details',
+ 'page arguments' => array(3),
+ 'access arguments' => array('access content'),
+ 'type' => MENU_CALLBACK,
+ );
+
+ $items['admin/store/orders/%uc_order/payment_details/%'] = array(
+ 'title' => 'Payment details',
+ 'description' => 'Add the payment details to the order pane.',
+ 'page callback' => 'uc_payment_get_details',
+ 'page arguments' => array(5, 'order', 3),
+ 'access arguments' => array('edit orders'),
+ 'type' => MENU_CALLBACK,
+ );
+
+ $items['admin/store/orders/%uc_order/payments/select/%'] = array(
+ 'title' => 'Select payment gateway',
+ 'page callback' => 'uc_payment_gateway_select',
+ 'access arguments' => array('view all orders'),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'uc_payment.admin.inc',
+ );
+ $items['admin/store/orders/%uc_order/payments'] = array(
+ 'title' => 'Payments',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_payment_by_order_form', 3),
+ 'access callback' => 'uc_payment_tracking_access',
+ 'weight' => 5,
+ 'type' => MENU_LOCAL_TASK,
+ 'file' => 'uc_payment.admin.inc',
+ );
+ $items['admin/store/orders/%uc_order/payments/%uc_payment/delete'] = array(
+ 'title' => 'Delete payment?',
+ 'description' => 'Delete payment?',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_payment_delete_confirm_form', 3, 5),
+ 'access callback' => 'uc_payment_delete_access',
+ 'type' => MENU_CALLBACK,
+ 'file' => 'uc_payment.admin.inc',
+ );
+
+ return $items;
+}
+
+/**
+ * Implements hook_token_values().
+ */
+function uc_payment_token_values($type, $object = NULL) {
+ $values = array();
+
+ switch ($type) {
+ case 'order':
+ $order = $object;
+ $values['order-payment-method'] = _payment_method_data($order->payment_method, 'review');
+ if (empty($values['order-payment-method'])) {
+ $values['order-payment-method'] = _payment_method_data($order->payment_method, 'name');
+ }
+
+ $context = array(
+ 'revision' => 'formatted',
+ 'type' => 'amount',
+ );
+ $values['order-payment-balance'] = uc_price(uc_payment_balance($order), $context);
+ break;
+ }
+
+ return $values;
+}
+
+/**
+ * Implements hook_token_list(). (token.module)
+ */
+function uc_payment_token_list($type = 'all') {
+ $tokens = array();
+
+ if ($type == 'order' || $type == 'ubercart' || $type == 'all') {
+ $tokens['order']['order-payment-method'] = t('The payment method of the order.');
+ $tokens['order']['order-payment-balance'] = t('The payment balance of the order');
+ }
+
+ return $tokens;
+}
+
+/**
+ * Implements hook_perm().
+ */
+function uc_payment_perm() {
+ return array('view payments', 'manual payments', 'delete payments');
+}
+
+/**
+ * Access callback to view list of payments.
+ */
+function uc_payment_tracking_access() {
+ return user_access('view payments') && variable_get('uc_payment_tracking', TRUE);
+}
+
+/**
+ * Access callback to delete a payment.
+ */
+function uc_payment_delete_access() {
+ return user_access('delete payments') && variable_get('uc_payment_deleting', TRUE);
+}
+
+/**
+ * Implements hook_theme().
+ */
+function uc_payment_theme() {
+ return array(
+ 'uc_payment_method_table' => array(
+ 'arguments' => array('form' => NULL),
+ 'file' => 'uc_payment.admin.inc',
+ ),
+ 'uc_payment_by_order_form' => array(
+ 'arguments' => array('form' => NULL),
+ 'file' => 'uc_payment.admin.inc',
+ ),
+ 'uc_payment_method_select' => array(
+ 'arguments' => array('form' => NULL),
+ ),
+ );
+}
+
+/**
+ * Implements hook_init().
+ */
+function uc_payment_init() {
+ global $conf;
+ $conf['i18n_variables'][] = 'uc_default_payment_msg';
+}
+
+/**
+ * Implements hook_form_alter().
+ */
+function uc_payment_form_alter(&$form, $form_state, $form_id) {
+ if ($form_id == 'uc_cart_checkout_form') {
+ drupal_add_js('misc/progress.js');
+ drupal_add_js(drupal_get_path('module', 'uc_payment') .'/uc_payment.js');
+ }
+}
+
+
+/*******************************************************************************
+ * Hook Functions (Ubercart)
+ ******************************************************************************/
+
+/**
+ * Implements hook_order().
+ */
+function uc_payment_order($op, $order) {
+ switch ($op) {
+ case 'submit':
+ $func = _payment_method_data($order->payment_method, 'callback');
+ if (function_exists($func)) {
+ return $func('order-submit', $order);
+ }
+ break;
+
+ case 'load':
+ $func = _payment_method_data($order->payment_method, 'callback');
+ if (function_exists($func)) {
+ $func('order-load', $order);
+ }
+ break;
+
+ case 'save':
+ $func = _payment_method_data($order->payment_method, 'callback');
+ if (function_exists($func)) {
+ $func('order-save', $order);
+ }
+ break;
+
+ case 'can_delete':
+ if (uc_payment_load_payments($order->order_id) !== FALSE) {
+ return FALSE;
+ }
+ break;
+
+ case 'delete':
+ db_query("DELETE FROM {uc_payment_receipts} WHERE order_id = %d", $order->order_id);
+ // Call each payment method to delete method specific data from the database.
+ $methods = _payment_method_list();
+ foreach ($methods as $method) {
+ $func = $method['callback'];
+ if (function_exists($func)) {
+ $func('order-delete', $order);
+ }
+ }
+ break;
+ }
+}
+
+/**
+ * Implements hook_checkout_pane().
+ */
+function uc_payment_checkout_pane() {
+ $panes[] = array(
+ 'id' => 'payment',
+ 'title' => t('Payment method'),
+ 'desc' => t('Select a payment method from the enabled payment modules.'),
+ 'callback' => 'uc_checkout_pane_payment',
+ 'weight' => 6,
+ );
+
+ return $panes;
+}
+
+/**
+ * Implements hook_order_pane().
+ */
+function uc_payment_order_pane() {
+ $panes[] = array(
+ 'id' => 'payment',
+ 'callback' => 'uc_order_pane_payment',
+ 'title' => t('Payment'),
+ 'desc' => t('Specify and collect payment for an order.'),
+ 'class' => 'pos-left',
+ 'weight' => 4,
+ 'show' => array('view', 'edit', 'customer'), //, 'invoice', 'customer'),
+ );
+
+ return $panes;
+}
+
+/**
+ * Implements hook_order_state().
+ */
+function uc_payment_order_state() {
+ $states[] = array(
+ 'id' => 'payment_received',
+ 'title' => t('Payment received'),
+ 'weight' => 10,
+ 'scope' => 'general',
+ );
+
+ return $states;
+}
+
+
+/*******************************************************************************
+ * Callback Functions, Forms, and Tables
+ ******************************************************************************/
+
+/**
+ * Returns a formatted list of line items for an order total preview.
+ *
+ * @param $return
+ * TRUE or FALSE to specify whether or not to return the results instead of
+ * printing them and exiting.
+ * @param $order
+ * Optionally pass in a full order object to use instead of finding it in the
+ * $_POST data.
+ *
+ * @return
+ * The formatted HTML of the order total preview if $return is set to TRUE.
+ */
+function uc_payment_get_totals($return = FALSE, $order = NULL) {
+ $output = '';
+
+ if (empty($order) && is_array($_POST) && isset($_POST['order'])) {
+ $order = unserialize($_POST['order']);
+ }
+
+ if ($order) {
+ usort($order->line_items, 'uc_weight_sort');
+
+ $output = t('Order total preview:')
+ .' <span id="order-total-throbber"></span><table>';
+ $grand_total = 0;
+
+ $context = array(
+ 'type' => 'line_item',
+ 'subject' => array(
+ 'order' => $order,
+ ),
+ );
+
+ foreach ($order->line_items as $line) {
+ if (!empty($line['title'])) {
+ $context['revision'] = 'themed';
+ $context['subject']['line_item'] = $line;
+
+ $output .= '<tr><td align="right"><b>'. filter_xss($line['title']) .':</b></td>'
+ .'<td align="right">'. uc_price($line['amount'], $context) .'</td></tr>';
+
+ if ($line['summed']) {
+ $context['revision'] = 'altered';
+ }
+ }
+ }
+
+ $context['revision'] = 'themed';
+ $context['type'] = 'amount';
+ unset($context['subject']);
+ $output .= '<tr><td align="right"><b>'. t('Order total:') .'</b></td>'
+ .'<td align="right">'. uc_price(uc_order_get_total($order), $context)
+ .'</td></tr></table>';
+ }
+
+ if ($return) {
+ return $output;
+ }
+
+ print $output;
+ exit();
+}
+
+function uc_payment_get_details($method_id, $view = 'cart', $order = NULL) {
+ if ($view == 'cart') {
+ if (!($order = uc_order_load($_SESSION['cart_order']))) {
+ $_SESSION['cart_order'] = NULL;
+ $order = NULL;
+ }
+
+ if ($order->order_status != 0 || ($user->uid && $user->uid != $order->uid)) {
+ $order = NULL;
+ }
+ }
+
+ $func = _payment_method_data($method_id, 'callback');
+ if (function_exists($func)) {
+ $output = $func($view .'-details', $order);
+ }
+
+ print $output;
+ exit();
+}
+
+function _total_sort($a, $b) {
+ if ($a[0] == $b[0]) {
+ return 0;
+ }
+
+ return ($a[0] < $b[0]) ? -1 : 1;
+}
+
+/**
+ * TAPIr table definition for uc_payments_table.
+ */
+function uc_payments_table() {
+ $table = array(
+ '#type' => 'tapir_table',
+ '#tree' => TRUE,
+ '#columns' => array(
+ 'received' => array(
+ 'cell' => t('Received'),
+ 'weight' => 0,
+ ),
+ 'user' => array(
+ 'cell' => t('User'),
+ 'weight' => 1,
+ ),
+ 'method' => array(
+ 'cell' => t('Method'),
+ 'weight' => 2,
+ ),
+ 'amount' => array(
+ 'cell' => t('Amount'),
+ 'weight' => 3,
+ ),
+ 'balance' => array(
+ 'cell' => t('Balance'),
+ 'weight' => 4,
+ ),
+ 'comment' => array(
+ 'cell' => t('Comment'),
+ 'weight' => 5,
+ ),
+ 'action' => array(
+ 'cell' => t('Action'),
+ 'weight' => 6,
+ ),
+ ),
+ '#rows' => array(),
+ );
+
+ return $table;
+}
+
+/*******************************************************************************
+ * Module and Helper Functions
+ ******************************************************************************/
+
+/**
+ * Processes a payment through an enabled payment gateway.
+ *
+ * @param $method
+ * The ID of the payment method to use to process the payment.
+ * @param $order_id
+ * The ID of the order associated with this payment.
+ * @param $amount
+ * The amount of the payment we're attempting to collect.
+ * @param $data
+ * An array of data passed on to the payment gateway module used to process
+ * the payment for the specified payment method.
+ * @param $default
+ * TRUE or FALSE to indicate we're forcing the use of the default gateway for
+ * the specified payment method. When TRUE, admin messages related to the
+ * payment will be hidden from display so customers don't see them.
+ * @param $selected
+ * The ID of a payment gateway to use to process the payment; normally comes
+ * from the payment gateway select form.
+ * @param $redirect
+ * TRUE or FALSE to indicate whether or not to redirect back to the admin
+ * order view page for the order referenced in $order_id.
+ *
+ * @return
+ * TRUE or FALSE indicating whether or not the payment was processed.
+ */
+function uc_payment_process($method, $order_id, $amount, $data = NULL, $default = FALSE, $selected = NULL, $redirect = TRUE) {
+ $result = array();
+
+ // Get an array of enabled payment gateways available for the payment method.
+ $gateways = _payment_gateway_list($method, TRUE);
+
+ // Fail if no gateways were found for the specified method.
+ if (empty($gateways)) {
+ // Display an error message if messages weren't silenced.
+ if (!$default) {
+ drupal_set_message(t('You are not able to process %type payments.', array('%type' => _payment_method_data($method, 'name'))));
+ }
+
+ return FALSE;
+ }
+
+ // If we only found one gateway for this payment method...
+ if (count($gateways) == 1) {
+ // Get the right key for the payment gateway in the array.
+ $key = array_shift(array_keys($gateways));
+
+ // If we can find a callback in the gateway for the payment method...
+ if (function_exists($gateways[$key][$method])) {
+ // Pass the payment data onto the callback and store the result.
+ $result = $gateways[$key][$method]($order_id, $amount, $data);
+ }
+ else {
+ // Otherwise display a failure message to administrators.
+ if (user_access('administer store')) {
+ drupal_set_message(t("Attempted to process a %type payment but the gateway's function was not found.", array('%type' => _payment_method_data($method, 'name'))));
+ }
+
+ $result['success'] = FALSE;
+ }
+ }
+ else {
+ // Otherwise attempt to find the appropriate gateway function in the array.
+ $callback = FALSE;
+
+ foreach ($gateways as $gateway) {
+ // If we want the default gateway and this is it, store the callback
+ // and continue.
+ if ($default && $gateway['id'] == variable_get('uc_payment_'. $method .'_gateway', '')) {
+ $callback = $gateway[$method];
+ continue;
+ }
+
+ // If we want to use a specific gateway and this is it, store the callback.
+ if (!empty($selected) && $gateway['id'] == $selected) {
+ $callback = $gateway[$method];
+ }
+ }
+
+ // If we found a callback...
+ if ($callback !== FALSE) {
+ // Check to see if the function exists and process the payment.
+ if (function_exists($callback)) {
+ $result = $callback($order_id, $amount, $data);
+ }
+ else {
+ // Otherwise display an error message to administrators.
+ if (user_access('administer store')) {
+ drupal_set_message(t('An error has occurred with your payment gateway. The charge function could not be found.'));
+ }
+
+ $result['success'] = FALSE;
+ }
+ }
+ else {
+ // Otherwise store the info that was passed to us in the session and
+ // redirect to a form where we can choose a payment gateway.
+ $_SESSION['uc_payment_method'] = $method;
+ $_SESSION['uc_payment_order_id'] = $order_id;
+ $_SESSION['uc_payment_amount'] = $amount;
+ $_SESSION['uc_payment_data'] = serialize($data);
+
+ drupal_goto('admin/store/orders/'. $order_id .'/payments/select/'. $method);
+ }
+ }
+
+ // If the payment processed successfully...
+ if ($result['success'] === TRUE) {
+ // Log the payment to the order if not disabled.
+ if ($result['log_payment'] !== FALSE) {
+ uc_payment_enter($order_id, $method, $amount, empty($result['uid']) ? 0 : $result['uid'], $result['data'], $result['comment']);
+ }
+ }
+ else {
+ // Otherwise display the failue message in the logs.
+ watchdog('uc_payment', 'Payment failed for order @order_id: @message', array('@order_id' => $order_id, '@message' => $result['message']), WATCHDOG_WARNING, l(t('view order'), 'admin/store/orders/'. $order_id));
+ }
+
+ // If we have a message for display and aren't simply charging with the
+ // default gateway for a customer...
+ if (!empty($result['message']) && !$default) {
+ drupal_set_message($result['message']);
+ }
+
+ // Head back to the order if a redirect was specified.
+ if ($redirect) {
+ drupal_goto('admin/store/orders/'. $order_id);
+ }
+
+ return $result['success'];
+}
+
+/**
+ * Enters a payment for an order.
+ *
+ * @param $order_id
+ * The order ID to apply the payment to.
+ * @param $method
+ * The payment method ID.
+ * @param $amount
+ * The amount of the payment.
+ * @param $uid
+ * (optional) The user ID of the person logging the payment, or 0 if the
+ * payment was processed automatically.
+ * @param $data
+ * (optional) Any data that should be serialized and stored with the
+ * payment.
+ * @param $comment
+ * (optional) The comment to enter in the payment log.
+ * @param $received
+ * (optional) The timestamp at which the payment was received.
+ */
+function uc_payment_enter($order_id, $method, $amount, $uid = 0, $data = NULL, $comment = '', $received = NULL) {
+ if ($received == NULL) {
+ $received = time();
+ }
+ $method_name = _payment_method_data($method, 'review');
+ if (empty($method_name)) {
+ $method_name = _payment_method_data($method, 'name');
+ }
+ if (is_null($method_name)) {
+ $method_name = t('Other');
+ }
+ if (is_array($data)) {
+ $data = serialize($data);
+ }
+
+ if (variable_get('uc_payment_logging', TRUE)) {
+ global $user;
+ $context = array(
+ 'revision' => 'formatted',
+ 'type' => 'amount',
+ );
+ $log_message = t('@method payment for @amount entered by @user.', array('@method' => $method_name, '@amount' => uc_price($amount, $context), '@user' => uc_get_initials($user->uid)));
+ uc_order_log_changes($order_id, array($log_message));
+ }
+
+ db_query("INSERT INTO {uc_payment_receipts} (order_id, method, amount, uid, data, comment, received) VALUES (%d, '%s', %f, %d, '%s', '%s', %d)",
+ $order_id, $method_name, $amount, $uid, $data, $comment, $received);
+
+ $order = uc_order_load($order_id);
+ $account = user_load($uid);
+
+ // Ensure user has an account before payment is made.
+ uc_cart_complete_sale($order);
+
+ module_invoke_all('uc_payment_entered', $order, $method, $amount, $account, $data, $comment);
+ ca_pull_trigger('uc_payment_entered', $order, $account);
+}
+
+/**
+ * Deletes a payment from the database.
+ */
+function uc_payment_delete($receipt_id) {
+ if (!is_numeric($receipt_id)) {
+ return FALSE;
+ }
+
+ if (variable_get('uc_payment_logging', TRUE)) {
+ global $user;
+ $payment = uc_payment_load($receipt_id);
+ $context = array(
+ 'revision' => 'formatted',
+ 'type' => 'payment',
+ 'subject' => array(
+ 'payment' => $payment,
+ ),
+ );
+ $log_message = t('@method payment for @amount deleted by @user.', array('@method' => $payment->method, '@amount' => uc_price($payment->amount, $context), '@user' => uc_get_initials($user->uid)));
+ uc_order_log_changes($payment->order_id, array($log_message));
+ }
+
+ db_query("DELETE FROM {uc_payment_receipts} WHERE receipt_id = %d", $receipt_id);
+}
+
+/**
+ * Returns the balance of payments on an order.
+ */
+function uc_payment_balance($order) {
+ $total = $order->order_total;
+ $payments = uc_payment_load_payments($order->order_id);
+
+ if ($payments === FALSE) {
+ return $total;
+ }
+
+ foreach ($payments as $payment) {
+ $total -= $payment->amount;
+ }
+
+ return $total;
+}
+
+/**
+ * Loads a single payment from the database by receipt_id.
+ */
+function uc_payment_load($receipt_id) {
+ if (!is_numeric($receipt_id)) {
+ return FALSE;
+ }
+
+ $result = db_query("SELECT * FROM {uc_payment_receipts} WHERE receipt_id = %d ", $receipt_id);
+ $payment = db_fetch_object($result);
+
+ return $payment;
+}
+
+/**
+ * Loads an array of all the payments for an order.
+ *
+ * @param $order_id
+ * The order's id.
+ * @param $action
+ * Unused...
+ *
+ * @return
+ * Array of payment objects or FALSE if there are none.
+ */
+function uc_payment_load_payments($order_id, $action = NULL) {
+ $payments = array();
+
+ $result = db_query("SELECT * FROM {uc_payment_receipts} WHERE order_id = %d "
+ ."ORDER BY received ASC", $order_id);
+ while ($payment = db_fetch_object($result)) {
+ $payments[] = $payment;
+ }
+
+ if (count($payments) == 0) {
+ $payments = FALSE;
+ }
+
+ return $payments;
+}
+
+/**
+ * Builds a list of payment methods defined in the enabled modules.
+ */
+function _payment_method_list($action = NULL) {
+ static $methods;
+
+ if (count($methods) > 0 && $action !== 'rebuild') {
+ return $methods;
+ }
+
+ $methods = module_invoke_all('payment_method');
+
+ // Allow other modules to alter the payment methods.
+ drupal_alter('payment_method', $methods);
+
+ foreach ($methods as $i => $value) {
+ $methods[$i]['checkout'] = variable_get('uc_payment_method_'. $methods[$i]['id'] .'_checkout', $methods[$i]['checkout']);
+ $methods[$i]['weight'] = variable_get('uc_payment_method_'. $methods[$i]['id'] .'_weight', $methods[$i]['weight']);
+ }
+ usort($methods, 'uc_weight_sort');
+
+ return $methods;
+}
+
+/**
+ * Returns data from a payment method by method ID and the array key.
+ */
+function _payment_method_data($method_id, $key) {
+ $methods = _payment_method_list();
+ foreach ($methods as $method) {
+ if ($method['id'] == $method_id) {
+ return isset($method[$key]) ? $method[$key] : NULL;
+ }
+ }
+}
+
+/**
+ * Builds a list of payment gateways defined in the enabled modules.
+ */
+function _payment_gateway_list($filter = NULL, $enabled_only = FALSE) {
+ $gateways = module_invoke_all('payment_gateway');
+
+ // Allow other modules to alter the payment gateways.
+ drupal_alter('payment_gateway', $gateways);
+
+ foreach ($gateways as $i => $value) {
+ $gateways[$i]['enabled'] = variable_get('uc_pg_'. $gateways[$i]['id'] .'_enabled', TRUE);
+ if ($filter != NULL) {
+ if (!isset($gateways[$i][$filter]) || !function_exists($gateways[$i][$filter])) {
+ unset($gateways[$i]);
+ continue;
+ }
+ }
+ if ($enabled_only) {
+ if (!variable_get('uc_pg_'. $gateways[$i]['id'] .'_enabled', TRUE)) {
+ unset($gateways[$i]);
+ }
+ }
+ }
+
+ return $gateways;
+}
+
+/**
+ * Returns data from a payment gateway by gateway ID and the array key.
+ *
+ * @param $gateway_id
+ * The ID of the payment gateway to query.
+ * @param $key
+ * The key of the data being requested.
+ *
+ * @return
+ * The requested data.
+ */
+function _payment_gateway_data($gateway_id, $key) {
+ // Load all the payment gateways.
+ $gateways = _payment_gateway_list();
+
+ // Loop through the array to find the matching gateway.
+ foreach ($gateways as $gateway) {
+ // If this is it, return the requested data.
+ if ($gateway['id'] == $gateway_id) {
+ return isset($gateway[$key]) ? $gateway[$key] : NULL;
+ }
+ }
+}
diff -Naur nohack/sites/all/modules/ubercart/uc_cart/uc_cart.module_29_05_2012 dev/sites/all/modules/ubercart/uc_cart/uc_cart.module_29_05_2012
--- nohack/sites/all/modules/ubercart/uc_cart/uc_cart.module_29_05_2012 1970-01-01 07:00:00.000000000 +0700
+++ dev/sites/all/modules/ubercart/uc_cart/uc_cart.module_29_05_2012 2012-05-15 06:54:35.000000000 +0700
@@ -0,0 +1,1746 @@
+<?php
+
+/**
+ * @file
+ * Handles all things concerning Ubercart's shopping cart.
+ *
+ * The Ubercart cart system functions much like the e-commerce cart at its base
+ * level... in fact, most carts do. This module handles the cart display,
+ * adding items to a cart, and checking out. The module enables the cart,
+ * products, and checkout to be extensible.
+ */
+
+require_once('uc_cart_checkout_pane.inc');
+require_once('uc_cart.ca.inc');
+
+/*******************************************************************************
+ * Hook Functions (Drupal)
+ ******************************************************************************/
+
+/**
+ * Implements hook_menu().
+ */
+function uc_cart_menu() {
+ $items = array();
+
+ $items['admin/store/settings/cart'] = array(
+ 'title' => 'Cart settings',
+ 'description' => 'Configure the cart settings.',
+ 'page callback' => 'uc_cart_cart_settings_overview',
+ 'access arguments' => array('administer store'),
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/cart/overview'] = array(
+ 'title' => 'Overview',
+ 'description' => 'View the cart settings.',
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ 'weight' => -10,
+ );
+ $items['admin/store/settings/cart/edit'] = array(
+ 'title' => 'Edit',
+ 'description' => 'Edit the cart settings.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_cart_cart_settings_form'),
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => -5,
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/cart/edit/basic'] = array(
+ 'title' => 'Cart settings',
+ 'description' => 'Edit the basic cart settings.',
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ 'weight' => -10,
+ );
+ $items['admin/store/settings/cart/edit/panes'] = array(
+ 'title' => 'Cart panes',
+ 'description' => 'Edit the pane settings for the cart view page.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_cart_cart_panes_form'),
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => -5,
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/cart/edit/block'] = array(
+ 'title' => 'Cart block',
+ 'description' => 'Edit the settings for the shopping cart block.',
+ 'page callback' => 'uc_cart_block_edit_info',
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => 0,
+ 'file' => 'uc_cart.admin.inc',
+ );
+
+ $items['admin/store/settings/checkout'] = array(
+ 'title' => 'Checkout settings',
+ 'description' => 'Configure the checkout settings.',
+ 'page callback' => 'uc_cart_checkout_settings_overview',
+ 'access arguments' => array('administer store'),
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/checkout/overview'] = array(
+ 'title' => 'Overview',
+ 'description' => 'View the checkout settings.',
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ 'weight' => -10,
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/checkout/edit'] = array(
+ 'title' => 'Edit',
+ 'description' => 'Edit the cart settings.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_cart_checkout_settings_form'),
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => -5,
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/checkout/edit/basic'] = array(
+ 'title' => 'Checkout settings',
+ 'description' => 'Edit the basic checkout settings.',
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_DEFAULT_LOCAL_TASK,
+ 'weight' => -10,
+ );
+ $items['admin/store/settings/checkout/edit/panes'] = array(
+ 'title' => 'Checkout panes',
+ 'description' => 'Edit the pane settings for the checkout page.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_cart_checkout_panes_form'),
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => -5,
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/checkout/edit/messages'] = array(
+ 'title' => 'Checkout messages',
+ 'description' => 'Edit the messages for the checkout completion page.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_cart_checkout_messages_form'),
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => 0,
+ 'file' => 'uc_cart.admin.inc',
+ );
+ $items['admin/store/settings/checkout/edit/fields'] = array(
+ 'title' => 'Address fields',
+ 'description' => 'Edit the address field settings.',
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array('uc_store_address_fields_form'), // missing?
+ 'access arguments' => array('administer store'),
+ 'type' => MENU_LOCAL_TASK,
+ 'weight' => 5,
+ 'file' => 'uc_cart.admin.inc',
+ );
+
+ $items['cart'] = array(
+ 'title' => 'Shopping cart',
+ 'description' => 'View/modify the contents of your shopping cart or proceed to checkout.',
+ 'page callback' => 'uc_cart_view',
+ 'access arguments' => array('access content'),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'uc_cart.pages.inc',
+ );
+ $items['cart/checkout'] = array(
+ 'title' => 'Checkout',
+ 'description' => 'Purchase the items in your shopping cart.',
+ 'page callback' => 'uc_cart_checkout',
+ 'access arguments' => array('access content'),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'uc_cart.pages.inc',
+ );
+ $items['cart/checkout/review'] = array(
+ 'title' => 'Review order',
+ 'description' => 'Review an order before final submission.',
+ 'page callback' => 'uc_cart_checkout_review',
+ 'access arguments' => array('access content'),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'uc_cart.pages.inc',
+ );
+ $items['cart/checkout/complete'] = array(
+ 'title' => 'Order complete',
+ 'description' => 'Display information upon completion of an order.',
+ 'page callback' => 'uc_cart_checkout_complete',
+ 'access arguments' => array('access content'),
+ 'type' => MENU_CALLBACK,
+ 'file' => 'uc_cart.pages.inc',
+ );
+
+ return $items;
+}
+
+/**
+ * Implements hook_imagecache_default_presets().
+ */
+function uc_cart_imagecache_default_presets() {
+ $presets = array();
+
+ $presets['cart'] = array(
+ 'presetname' => 'cart',
+ 'actions' => array(
+ array(
+ 'weight' => '0',
+ 'module' => 'uc_cart',
+ 'action' => 'imagecache_scale',
+ 'data' => array(
+ 'width' => '50',
+ 'height' => '50',
+ 'upscale' => 0,
+ ),
+ ),
+ ),
+ );
+
+ return $presets;
+}
+
+/**
+ * Implements hook_theme().
+ */
+function uc_cart_theme() {
+ return array(
+ 'uc_cart_block_title' => array(
+ 'arguments' => array('title' => NULL, 'icon_class' => FALSE, 'collapsible' => FALSE),
+ ),
+ 'uc_cart_block_title_icon' => array(
+ 'arguments' => array('icon_class' => NULL),
+ ),
+ 'uc_cart_block_content_cachable' => array(
+ 'arguments' => array(),
+ ),
+ 'uc_cart_block_content' => array(
+ 'arguments' => array('help_text' => NULL, 'items' => NULL, 'item_count' => NULL, 'item_text' => NULL, 'total' => NULL, 'summary_links' => NULL),
+ ),
+ 'uc_cart_block_items' => array(
+ 'arguments' => array('items' => NULL),
+ ),
+ 'uc_cart_block_summary' => array(
+ 'arguments' => array('item_count' => NULL, 'item_text' => NULL, 'total' => NULL, 'summary_links' => NULL),
+ ),
+ 'uc_empty_cart' => array(
+ 'arguments' => array(),
+ ),
+ 'uc_cart_view_form' => array(
+ 'arguments' => array('form' => NULL),
+ ),
+ 'uc_cart_view_price' => array(
+ 'arguments' => array('form' => NULL),
+ ),
+ 'address_pane' => array(
+ 'arguments' => array('form' => NULL),
+ ),
+ 'cart_review_table' => array(
+ 'arguments' => array('show_subtotal' => TRUE),
+ ),
+ 'uc_cart_checkout_form' => array(
+ 'arguments' => array('form' => NULL),
+ 'file' => 'uc_cart.pages.inc',
+ ),
+ 'uc_cart_checkout_review' => array(
+ 'arguments' => array('panes' => NULL, 'form' => NULL),
+ 'file' => 'uc_cart.pages.inc',
+ ),
+ 'uc_checkout_pane_cart_review' => array(
+ 'arguments' => array('items' => NULL),
+ 'file' => 'uc_cart_checkout_pane.inc',
+ ),
+ 'uc_cart_complete_sale' => array(
+ 'arguments' => array('message' => NULL, 'order' => NULL),
+ ),
+ );
+}
+
+/**
+ * Implements hook_init().
+ */
+function uc_cart_init() {
+ global $conf;
+ $conf['i18n_variables'][] = 'uc_cart_breadcrumb_text';
+ $conf['i18n_variables'][] = 'uc_cart_help_text';
+ $conf['i18n_variables'][] = 'uc_cart_new_account_details';
+ $conf['i18n_variables'][] = 'uc_checkout_instructions';
+ $conf['i18n_variables'][] = 'uc_checkout_review_instructions';
+ $conf['i18n_variables'][] = 'uc_continue_shopping_text';
+ $conf['i18n_variables'][] = 'uc_minimum_subtotal_text';
+ $conf['i18n_variables'][] = 'uc_msg_continue_shopping';
+ $conf['i18n_variables'][] = 'uc_msg_order_existing_user';
+ $conf['i18n_variables'][] = 'uc_msg_order_logged_in';
+ $conf['i18n_variables'][] = 'uc_msg_order_new_user';
+ $conf['i18n_variables'][] = 'uc_msg_order_new_user_logged_in';
+ $conf['i18n_variables'][] = 'uc_msg_order_submit';
+
+ // Don't cache any cart of checkout pages.
+ // Code based on CacheExclude - http://drupal.org/project/cacheexclude
+ if (arg(0) == 'cart') {
+ $GLOBALS['conf']['cache'] = 0;
+ }
+}
+
+/**
+ * Implements hook_cron().
+ */
+function uc_cart_cron() {
+ // Empty anonymous carts.
+ $time = strtotime(variable_get('uc_cart_anon_duration', '4') .' '. variable_get('uc_cart_anon_unit', 'hours') .' ago');
+ $result = db_query("SELECT DISTINCT cart_id FROM {uc_cart_products} WHERE changed <= %d AND CHAR_LENGTH(cart_id) >= 22", $time);
+ while ($row = db_fetch_object($result)) {
+ uc_cart_empty($row->cart_id);
+ }
+
+ // Empty authenticated carts.
+ $time = strtotime(variable_get('uc_cart_auth_duration', '1') .' '. variable_get('uc_cart_auth_unit', 'years') .' ago');
+ $result = db_query("SELECT DISTINCT cart_id FROM {uc_cart_products} WHERE changed <= %d AND CHAR_LENGTH(cart_id) < 22", $time);
+ while ($row = db_fetch_object($result)) {
+ uc_cart_empty($row->cart_id);
+ }
+}
+
+/**
+ * Implements hook_nodeapi().
+ */
+function uc_cart_nodeapi(&$node, $op, $arg3, $arg4) {
+ if (uc_product_is_product($node->type)) {
+ switch ($op) {
+ case 'delete':
+ db_query("DELETE FROM {uc_cart_products} WHERE nid = %d", $node->nid);
+ break;
+ }
+ }
+}
+
+/**
+ * Implements hook_user().
+ */
+function uc_cart_user($op, &$edit, &$user, $category = NULL) {
+ switch ($op) {
+ case 'load':
+ // Fall through if this a new user load prior to checkout.
+ if (request_uri() != '/user/register?destination=cart/checkout' || $user->uid == 0) {
+ break;
+ }
+ case 'login':
+ // Add items from an anonymous cart to a user's permanent cart on login.
+ uc_cart_login_update($user->uid);
+ break;
+ }
+}
+
+/**
+ * Implements hook_form_alter().
+ */
+function uc_cart_form_alter(&$form, $form_state, $form_id) {
+ if ($form_id == 'user_login' || $form_id == 'user_login_block') {
+ $form['#submit'] = array_merge(array('uc_cart_user_login_form_submit'), (array) $form['#submit']);
+ }
+}
+
+/**
+ * Implements hook_block().
+ */
+function uc_cart_block($op = 'list', $delta = 0, $edit = array()) {
+ global $user;
+
+ switch ($op) {
+ case 'list':
+ $blocks = array();
+
+ // TODO: Add sensible default settings for the cart block based on the
+ // docs at http://api.drupal.org/api/function/hook_block/6.
+ $blocks[0] = array(
+ 'info' => t('Shopping cart'),
+ 'cache' => BLOCK_NO_CACHE,
+ );
+
+ return $blocks;
+
+ case 'configure':
+ // 0 = Default shopping cart block.
+ if ($delta == 0) {
+ return uc_cart_block_settings_form();
+ }
+ break;
+
+ case 'save':
+ // 0 = Default shopping cart block.
+ if ($delta == 0) {
+ uc_cart_block_settings_form_submit($edit);
+ }
+ break;
+
+ case 'view':
+ // 0 = Default shopping cart block.
+ if ($delta == 0) {
+ $cachable = !$user->uid && variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED;
+ $product_count = count(uc_cart_get_contents());
+
+ // Display nothing if the block is set to hide on empty and there are no
+ // items in the cart.
+ if (!$cachable && variable_get('uc_cart_block_empty_hide', FALSE) && !$product_count) {
+ return;
+ }
+
+ // Add the cart block CSS.
+ drupal_add_css(drupal_get_path('module', 'uc_cart') .'/uc_cart_block.css');
+
+ // If the block is collapsible, add the appropriate JS.
+ if (!$cachable && variable_get('uc_cart_block_collapsible', TRUE)) {
+ drupal_add_js(array('ucCollapsedBlock' => variable_get('uc_cart_block_collapsed', TRUE)), 'setting');
+ drupal_add_js(drupal_get_path('module', 'uc_cart') .'/uc_cart_block.js');
+ }
+
+ // Hack in some CSS to hide the block if necessary. drupal_add_css() is in Drupal 7 for this...
+ if (variable_get('uc_cart_block_collapsed', TRUE)) {
+ drupal_set_html_head("<style type='text/css'>#cart-block-contents { display: none; }</style>");
+ }
+
+ // Build the block content for display based on cache settings.
+ $block['subject'] = t('Shopping cart');
+ if ($cachable) {
+ // Caching is turned on and the user is not logged in, so we should
+ // deliver a block that is safe for caching.
+ $block['content'] = theme('uc_cart_block_content_cachable');
+ }
+ else {
+ // Otherwise build the whole shebang.
+
+ // First build the help text.
+ $help_text = FALSE;
+
+ if (variable_get('uc_cart_show_help_text', FALSE) && ($text = variable_get('uc_cart_help_text', t('Click title to display cart contents.')))) {
+ $help_text = check_plain($text);
+ }
+
+ $items = FALSE;
+ $item_count = 0;
+ $total = 0;
+
+ if ($product_count) {
+ foreach (uc_cart_get_contents() as $item) {
+ $display_item = module_invoke($item->module, 'cart_display', $item);
+
+ if (!empty($display_item)) {
+ $items[] = array(
+ 'nid' => $display_item['nid']['#value'],
+ 'qty' => t('@qty&times;', array('@qty' => $display_item['qty']['#default_value'])),
+ 'title' => $display_item['title']['#value'],
+ 'price' => $display_item['#total'],
+ 'desc' => isset($display_item['description']['#value']) ? $display_item['description']['#value'] : FALSE,
+ );
+ $total += $display_item['#total'];
+ }
+
+ $item_count += $item->qty;
+ }
+ }
+
+ // Build the item count text and cart links.
+ $item_text = format_plural($item_count, '<span class="num-items">@count</span> Item', '<span class="num-items">@count</span> Items');
+
+ $summary_links = array(
+ 'cart-block-view-cart' => array(
+ 'title' => t('View cart'),
+ 'href' => 'cart',
+ 'attributes' => array('rel' => 'nofollow'),
+ ),
+ );
+
+ // Only add the checkout link if checkout is enabled.
+ if (variable_get('uc_checkout_enabled', TRUE)) {
+ $summary_links['cart-block-checkout'] = array(
+ 'title' => t('Checkout'),
+ 'href' => 'cart/checkout',
+ 'attributes' => array('rel' => 'nofollow'),
+ );
+ }
+
+ $block['content'] = theme('uc_cart_block_content', $help_text, $items, $item_count, $item_text, $total, $summary_links);
+ }
+
+ return $block;
+ }
+ break;
+ }
+}
+
+/**
+ * Builds the settings form used by the shopping cart block.
+ *
+ * @see uc_cart_block_settings_form_submit()
+ * @ingroup forms
+ */
+function uc_cart_block_settings_form() {
+ $form = array();
+
+ $form['uc_cart_block_empty_hide'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Hide block if cart is empty.'),
+ '#description' => t('This does not apply to anonymous users if page caching is enabled, as the same cached page will be served to all anonymous users whether or not they have items in their cart.'),
+ '#default_value' => variable_get('uc_cart_block_empty_hide', FALSE),
+ );
+ $form['uc_cart_block_image'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Display the shopping cart icon in the block title.'),
+ '#default_value' => variable_get('uc_cart_block_image', TRUE),
+ );
+ $form['uc_cart_block_collapsible'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Make the shopping cart block collapsible by clicking the name or arrow.'),
+ '#default_value' => variable_get('uc_cart_block_collapsible', TRUE),
+ );
+ $form['uc_cart_block_collapsed'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Display the shopping cart block collapsed by default.'),
+ '#default_value' => variable_get('uc_cart_block_collapsed', TRUE),
+ );
+ $form['uc_cart_show_help_text'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Display small help text in the shopping cart block.'),
+ '#default_value' => variable_get('uc_cart_show_help_text', FALSE),
+ );
+ $form['uc_cart_help_text'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Cart help text'),
+ '#description' => t('Displayed if the above box is checked.'),
+ '#default_value' => variable_get('uc_cart_help_text', t('Click title to display cart contents.')),
+ '#size' => 32,
+ );
+
+ return $form;
+}
+
+/**
+ * Saves the shopping cart block settings.
+ *
+ * @see uc_cart_block_settings_form()
+ */
+function uc_cart_block_settings_form_submit($edit = array()) {
+ variable_set('uc_cart_block_empty_hide', $edit['uc_cart_block_empty_hide']);
+ variable_set('uc_cart_block_image', $edit['uc_cart_block_image']);
+ variable_set('uc_cart_block_collapsible', $edit['uc_cart_block_collapsible']);
+ variable_set('uc_cart_block_collapsed', $edit['uc_cart_block_collapsed']);
+ variable_set('uc_cart_show_help_text', $edit['uc_cart_show_help_text']);
+ variable_set('uc_cart_help_text', $edit['uc_cart_help_text']);
+}
+
+/**
+ * Preprocesses the cart block output.
+ */
+function uc_cart_preprocess_block(&$variables) {
+ global $user;
+
+ if ($variables['block']->module == 'uc_cart' && $variables['block']->delta == 0 && $variables['block']->subject) {
+ $cachable = !$user->uid && variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED;
+ $collapsible = !$cachable && variable_get('uc_cart_block_collapsible', TRUE);
+
+ // Build the cart image if enabled.
+ if (variable_get('uc_cart_block_image', TRUE)) {
+ // If the cart is empty or we need a cachable cart block...
+ $product_count = count(uc_cart_get_contents());
+ if ($cachable || !$product_count) {
+ // Use the "empty" cart icon.
+ $icon_class = 'cart-block-icon-empty';
+ }
+ else {
+ // Otherwise use the "full" cart icon.
+ $icon_class = 'cart-block-icon-full';
+ }
+ }
+ else {
+ $icon_class = FALSE;
+ }
+
+ $variables['block']->subject = theme('uc_cart_block_title', $variables['block']->subject, $icon_class, $collapsible);
+ }
+}
+
+/**
+ * Themes the shopping cart block title
+ *
+ * @param $title
+ * The text to use for the title of the block.
+ * @param $icon_class
+ * Class to use for the cart icon image or FALSE if the icon is disabled.
+ * @param $collapsible
+ * TRUE or FALSE indicating whether or not the cart block is collapsible.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_cart_block_title($title, $icon_class = 'cart-empty', $collapsible = TRUE) {
+ $output = '';
+
+ // Add in the cart image if specified.
+ if ($icon_class) {
+ $output .= theme('uc_cart_block_title_icon', $icon_class);
+ }
+
+ // Add the main title span and text, with or without the arrow based on the
+ // cart block collapsibility settings.
+ if ($collapsible) {
+ $output .= '<span class="cart-block-title-bar" title="'. t('Show/hide shopping cart contents.') .'">'. $title .'<span class="cart-block-arrow"></span></span>';
+ }
+ else {
+ $output .= '<span class="cart-block-title-bar">'. $title .'</span>';
+ }
+
+ return $output;
+}
+
+/**
+ * Themes the shopping cart icon.
+ *
+ * @param $icon_class
+ * Class to use for the cart icon image, either cart-full or cart-empty.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_cart_block_title_icon($icon_class) {
+ return l('<span class="'. $icon_class .'" title="'. t('View your shopping cart.') .'"></span>', 'cart', array('html' => TRUE));
+}
+
+/**
+ * Themes the cachable shopping cart block content.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_cart_block_content_cachable() {
+ return t('<a href="!url">View</a> your shopping cart.', array('!url' => url('cart')));
+}
+
+/**
+ * Themes the shopping cart block content.
+ *
+ * @param $help_text
+ * Text to place in the small help text area beneath the cart block title or
+ * FALSE if disabled.
+ * @param $items
+ * An associative array of item information containing the keys 'qty',
+ * 'title', 'price', and 'desc'.
+ * @param $item_count
+ * The number of items in the shopping cart.
+ * @param $item_text
+ * A textual representation of the number of items in the shopping cart.
+ * @param $total
+ * The unformatted total of all the products in the shopping cart.
+ * @param $summary_links
+ * An array of links used in the cart summary.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_cart_block_content($help_text, $items, $item_count, $item_text, $total, $summary_links) {
+ $output = '';
+
+ // Add the help text if enabled.
+ if ($help_text) {
+ $output .= '<span class="cart-help-text">'. $help_text .'</span>';
+ }
+
+ // Add a wrapper div for use when collapsing the block.
+ $output .= '<div id="cart-block-contents">';
+
+ // Add a table of items in the cart or the empty message.
+ $output .= theme('uc_cart_block_items', $items);
+
+ $output .= '</div>';
+
+ // Add the summary section beneath the items table.
+ $output .= theme('uc_cart_block_summary', $item_count, $item_text, $total, $summary_links);
+
+ return $output;
+}
+
+/**
+ * Themes the table listing the items in the shopping cart block.
+ *
+ * @param $items
+ * An associative array of item information containing the keys 'qty',
+ * 'title', 'price', and 'desc'.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_cart_block_items($items) {
+ // If there are items in the shopping cart...
+ if ($items) {
+ $output = '<table class="cart-block-items"><tbody>';
+ $row_class = 'odd';
+
+ $context = array(
+ 'revision' => 'themed',
+ 'type' => 'price',
+ );
+
+ // Loop through each item.
+ foreach ($items as $item) {
+ $context['subject'] = array(
+ 'cart_item' => $item,
+ 'node' => node_load($item['nid']),
+ );
+ // Add the basic row with quantity, title, and price.
+ $output .= '<tr class="'. $row_class .'"><td class="cart-block-item-qty">'. $item['qty'] .'</td>'
+ .'<td class="cart-block-item-title">'. $item['title'] .'</td>'
+ .'<td class="cart-block-item-price">'. uc_price($item['price'], $context) .'</td></tr>';
+
+ // Add a row of description if necessary.
+ if ($item['desc']) {
+ $output .= '<tr class="'. $row_class .'"><td colspan="3" class="cart-block-item-desc">'. $item['desc'] .'</td></tr>';
+ }
+
+ // Alternate the class for the rows.
+ $row_class = ($row_class == 'odd') ? 'even' : 'odd';
+ }
+
+ $output .= '</tbody></table>';
+ }
+ else {
+ // Otherwise display an empty message.
+ $output = '<p class="uc-cart-empty">'. t('There are no products in your shopping cart.') .'</p>';
+ }
+
+ return $output;
+}
+
+/**
+ * Themes the summary table at the bottom of the default shopping cart block.
+ *
+ * @param $item_count
+ * The number of items in the shopping cart.
+ * @param $item_text
+ * A textual representation of the number of items in the shopping cart.
+ * @param $total
+ * The unformatted total of all the products in the shopping cart.
+ * @param $summary_links
+ * An array of links used in the summary.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_cart_block_summary($item_count, $item_text, $total, $summary_links) {
+ $context = array(
+ 'revision' => 'themed-original',
+ 'type' => 'amount',
+ );
+ // Build the basic table with the number of items in the cart and total.
+ $output = '<table class="cart-block-summary"><tbody><tr>'
+ .'<td class="cart-block-summary-items">'. $item_text .'</td>'
+ .'<td class="cart-block-summary-total"><label>'. t('Total:')
+ .'</label> '. uc_price($total, $context) .'</td></tr>';
+
+ // If there are products in the cart...
+ if ($item_count > 0) {
+ // Add a view cart link.
+ $output .= '<tr class="cart-block-summary-links"><td colspan="2">'
+ . theme('links', $summary_links) .'</td></tr>';
+ }
+
+ $output .= '</tbody></table>';
+
+ return $output;
+}
+
+
+/*******************************************************************************
+ * Hook Functions (Ubercart)
+ ******************************************************************************/
+
+/**
+ * Implements hook_uc_message().
+ */
+function uc_cart_uc_message() {
+ global $user;
+
+ $messages['checkout_instructions'] = '';
+ $messages['review_instructions'] = t("Your order is almost complete. Please review the details below and click 'Submit order' if all the information is correct. You may use the 'Back' button to make changes to your order if necessary.");
+ $messages['completion_message'] = t('Your order is complete! Your order number is [order-id].');
+ $messages['completion_logged_in'] = t('Thank you for shopping at [store-name]. While logged in, you may continue shopping or <a href="[order-url]">view your current order status</a> and order history.');
+ $messages['completion_existing_user'] = t("Thank you for shopping at [store-name]. Your current order has been attached to the account we found matching your e-mail address.\n\n<a href=\"!user_url\">Login</a> to view your current order status and order history. Remember to login when you make your next purchase for a faster checkout experience!", array('!user_url' => url('user')));
+ $messages['completion_new_user'] = t("Thank you for shopping at [store-name]. A new account has been created for you here that you may use to view your current order status.\n\n<a href=\"!user_url\">Login</a> to your new account using the following information:\n\n<strong>Username:</strong> !new_username\n<strong>Password:</strong> !new_password", array('!user_url' => url('user')));
+ $messages['completion_new_user_logged_in'] = t("Thank you for shopping at [store-name]. A new account has been created for you here that you may use to view your current order status.\n\nYour password and further instructions have been sent to your e-mail address.\n\nFor your convenience, you are already logged in with your newly created account.");
+ $messages['continue_shopping'] = t('<a href="[site-url]">Return to the front page.</a>');
+
+ return $messages;
+}
+
+/**
+ * Implements hook_cart_pane().
+ */
+function uc_cart_cart_pane($items) {
+ $body = '';
+ if (!is_null($items)) {
+ $body = '<div id="cart-form-pane">' . drupal_get_form('uc_cart_view_form', $items) . '</div>';
+ }
+
+ $panes[] = array(
+ 'id' => 'cart_form',
+ 'title' => t('Default cart form'),
+ 'enabled' => TRUE,
+ 'weight' => 0,
+ 'body' => $body,
+ );
+
+ return $panes;
+}
+
+/**
+ * Implements hook_checkout_pane().
+ */
+function uc_cart_checkout_pane() {
+ $panes[] = array(
+ 'id' => 'cart',
+ 'callback' => 'uc_checkout_pane_cart',
+ 'title' => t('Cart contents'),
+ 'desc' => t("Display the contents of a customer's shopping cart."),
+ 'weight' => 1,
+ 'process' => FALSE,
+ 'collapsible' => FALSE,
+ );
+ $panes[] = array(
+ 'id' => 'customer',
+ 'callback' => 'uc_checkout_pane_customer',
+ 'title' => t('Customer information'),
+ 'desc' => t('Get the necessary information to create a customer on the site.'),
+ 'weight' => 2,
+ );
+ $panes[] = array(
+ 'id' => 'delivery',
+ 'callback' => 'uc_checkout_pane_delivery',
+ 'title' => t('Delivery information'),
+ 'desc' => t('Get the information for where the order needs to ship.'),
+ 'weight' => 3,
+ 'shippable' => TRUE,
+ );
+ $panes[] = array(
+ 'id' => 'billing',
+ 'callback' => 'uc_checkout_pane_billing',
+ 'title' => t('Billing information'),
+ 'desc' => t('Get basic information needed to collect payment.'),
+ 'weight' => 4,
+ );
+ $panes[] = array(
+ 'id' => 'comments',
+ 'callback' => 'uc_checkout_pane_comments',
+ 'title' => t('Order comments'),
+ 'desc' => t('Allow a customer to put comments on an order.'),
+ 'weight' => 7,
+ );
+
+ return $panes;
+}
+
+/*******************************************************************************
+ * Callback Functions, Forms, and Tables
+ ******************************************************************************/
+
+/**
+ * When a user logs in, update their cart items before the session changes.
+ */
+function uc_cart_user_login_form_submit($form, &$form_state) {
+ global $user;
+ unset($_SESSION['checkout-redirect']);
+ uc_cart_login_update($user->uid);
+}
+
+/**
+ * Updates a user's cart to include items from their anonymous session.
+ */
+function uc_cart_login_update($uid) {
+ if (!isset($_SESSION['uc_cart_id'])) {
+ return;
+ }
+
+ // If there are items in the anonymous cart, consolidate them.
+ if ($items = uc_cart_get_contents($_SESSION['uc_cart_id'])) {
+ // Remove the anonymous cart items.
+ db_query("DELETE FROM {uc_cart_products} WHERE cart_id = '%s'", $_SESSION['uc_cart_id']);
+
+ // Merge the anonymous items into the user cart.
+ foreach ($items as $key => $item) {
+ uc_cart_add_item($item->nid, $item->qty, $item->data, $uid, FALSE, FALSE, FALSE);
+ }
+
+ // Unset the anonymous cart ID, it's no longer needed
+ unset($_SESSION['uc_cart_id']);
+ }
+}
+
+/**
+ * Returns the text displayed for an empty shopping cart.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_empty_cart() {
+ return '<p class="uc-cart-empty">'. t('There are no products in your shopping cart.') .'</p>';
+}
+
+/**
+ * Displays a page allowing the customer to view the contents of his or her cart.
+ *
+ * Handles simple or complex objects. Some cart items may have a list of
+ * products that they represent. These are displayed but are not able to
+ * be changed by the customer.
+ *
+ * @see uc_cart_view_form_submit()
+ * @see uc_cart_view_form_continue_shopping()
+ * @see uc_cart_view_form_checkout()
+ * @see theme_uc_cart_view_form()
+ * @see theme_uc_cart_view_price()
+ * @see uc_cart_view_table()
+ * @ingroup forms
+ */
+function uc_cart_view_form($form_state, $items = NULL) {
+ $form['items'] = array(
+ '#type' => 'tapir_table',
+ '#tree' => TRUE,
+ );
+
+ $context = array(
+ 'revision' => 'themed-original',
+ 'type' => 'amount',
+ );
+ $i = 0;
+ foreach ($items as $item) {
+ $display_item = module_invoke($item->module, 'cart_display', $item);
+ if (!empty($display_item)) {
+ $form['items'][$i] = $display_item;
+ $form['items'][$i]['image']['#value'] = uc_product_get_picture($display_item['nid']['#value'], 'cart');
+
+ $description = $display_item['title']['#value'] . $display_item['description']['#value'];
+ $form['items'][$i]['desc']['#value'] = $description;
+
+ $form['items'][$i]['cart_item_id'] = array(
+ '#type' => 'hidden',
+ '#value' => $item->cart_item_id,
+ );
+
+ if (isset($form['items'][$i]['remove'])) {
+ // Backward compatibility with old checkbox method.
+ if ($form['items'][$i]['remove']['#type'] == 'checkbox') {
+ $form['items'][$i]['remove'] = array('#type' => 'submit', '#value' => t('Remove'));
+ }
+
+ $form['items'][$i]['remove']['#name'] = 'remove-' . $i;
+ }
+
+ $form['items'][$i]['title']['#type'] = 'value';
+ $form['items'][$i]['description']['#type'] = 'value';
+
+ if (empty($display_item['qty'])) {
+ $form['items'][$i]['qty'] = array(
+ '#value' => '',
+ );
+ }
+
+ $form['items'][$i]['total'] = array(
+ '#value' => uc_price($display_item['#total'], $context),
+ '#theme' => 'uc_cart_view_price',
+ );
+ $i++;
+ }
+ }
+
+ $form['items'] = tapir_get_table('uc_cart_view_table', $form['items']);
+
+ // If the continue shopping element is enabled...
+ if (($cs_type = variable_get('uc_continue_shopping_type', 'link')) !== 'none') {
+ // Setup the text used for the element.
+ $cs_text = variable_get('uc_continue_shopping_text', '') ? variable_get('uc_continue_shopping_text', '') : t('Continue shopping');
+
+ // Add the element to the form based on the element type.
+ if (variable_get('uc_continue_shopping_type', 'link') == 'link') {
+ $form['continue_shopping'] = array(
+ '#value' => l($cs_text, uc_cart_continue_shopping_url()),
+ );
+ }
+ elseif (variable_get('uc_continue_shopping_type', 'link') == 'button') {
+ $form['continue_shopping'] = array(
+ '#type' => 'submit',
+ '#value' => $cs_text,
+ '#submit' => array('uc_cart_view_form_submit', 'uc_cart_view_form_continue_shopping'),
+ );
+ }
+ }
+
+ // Add the control buttons for updating and proceeding to checkout.
+ $form['update'] = array(
+ '#type' => 'submit',
+ '#name' => 'update-cart',
+ '#value' => t('Update cart'),
+ );
+ if (variable_get('uc_checkout_enabled', TRUE)) {
+ $form['checkout'] = array(
+ '#type' => 'submit',
+ '#value' => t('Checkout'),
+ '#submit' => array('uc_cart_view_form_submit', 'uc_cart_view_form_checkout'),
+ );
+ }
+
+ return $form;
+}
+
+/**
+ * Default submit handler for uc_cart_view_form().
+ *
+ * @see uc_cart_view_form()
+ */
+function uc_cart_view_form_submit($form, &$form_state) {
+ // Remove the cart order variable if the customer came here during checkout.
+ if (isset($_SESSION['cart_order'])) {
+ unset($_SESSION['cart_order']);
+ }
+
+ // If a remove button was clicked, set the quantity for that item to 0.
+ if (substr($form_state['clicked_button']['#name'], 0, 7) == 'remove-') {
+ $item = substr($form_state['clicked_button']['#name'], 7);
+ $form_state['values']['items'][$item]['qty'] = 0;
+ drupal_set_message(t('<strong>!product-title</strong> removed from your shopping cart.', array('!product-title' => $form_state['values']['items'][$item]['title'])));
+ }
+
+ // Update the items in the shopping cart based on the form values.
+ uc_cart_update_item_object((object)$form_state['values']);
+
+ if ($form_state['clicked_button']['#name'] == 'update-cart') {
+ drupal_set_message(t('Your cart has been updated.'));
+ }
+}
+
+/**
+ * Continue shopping redirect for uc_cart_view_form().
+ *
+ * @see uc_cart_view_form()
+ */
+function uc_cart_view_form_continue_shopping($form, &$form_state) {
+ $form_state['redirect'] = uc_cart_continue_shopping_url();
+}
+
+/**
+ * Checkout redirect for uc_cart_view_form().
+ *
+ * @see uc_cart_view_form()
+ */
+function uc_cart_view_form_checkout($form, &$form_state) {
+ $form_state['redirect'] = 'cart/checkout';
+}
+
+/**
+ * Themes the uc_cart_view_form().
+ *
+ * @see uc_cart_view_form()
+ * @ingroup themeable
+ */
+function theme_uc_cart_view_form($form) {
+ drupal_add_css(drupal_get_path('module', 'uc_cart') .'/uc_cart.css');
+
+ $output = '<div class="uc-default-submit">';
+ $output .= drupal_render($form['update']);
+ $output .= '</div>';
+ unset($form['update']['#printed']);
+
+ $output .= '<div id="cart-form-products">'
+ . drupal_render($form['items']) .'</div>';
+
+ foreach (element_children($form['items']) as $i) {
+ foreach (array('title', 'options', 'remove', 'image', 'qty') as $column) {
+ $form['items'][$i][$column]['#printed'] = TRUE;
+ }
+ $form['items'][$i]['#printed'] = TRUE;
+ }
+
+ // Add the continue shopping element and cart submit buttons.
+ if (($type = variable_get('uc_continue_shopping_type', 'link')) != 'none') {
+ // Render the continue shopping element into a variable.
+ $cs_element = drupal_render($form['continue_shopping']);
+
+ // Add the element with the appropriate markup based on the display type.
+ if ($type == 'link') {
+ $output .= '<div id="cart-form-buttons"><div id="continue-shopping-link">'
+ . $cs_element .'</div>'. drupal_render($form) .'</div>';
+ }
+ elseif ($type == 'button') {
+ $output .= '<div id="cart-form-buttons"><div id="update-checkout-buttons">'
+ . drupal_render($form) .'</div><div id="continue-shopping-button">'
+ . $cs_element .'</div></div>';
+ }
+ }
+ else {
+ $output .= '<div id="cart-form-buttons">'. drupal_render($form) .'</div>';
+ }
+
+ return $output;
+}
+
+/**
+ * Dumb wrapper function, as the price has been themed by uc_price() already.
+ *
+ * @see uc_cart_view_form()
+ * @ingroup themeable
+ */
+function theme_uc_cart_view_price($form) {
+ return $form['#value'];
+}
+
+/**
+ * Lists the products in the cart in a TAPIr table.
+ */
+function uc_cart_view_table($table) {
+ $table['#attributes'] = array('width' => '100%');
+
+ $table['#columns'] = array(
+ 'remove' => array(
+ 'cell' => t('Remove'),
+ 'weight' => 0,
+ ),
+ 'image' => array(
+ 'cell' => t('Products'),
+ 'weight' => 1,
+ ),
+ 'desc' => array(
+ 'cell' => '',
+ 'weight' => 2,
+ ),
+ 'qty' => array(
+ 'cell' => t('Qty.'),
+ 'weight' => 3,
+ ),
+ 'total' => array(
+ 'cell' => t('Total'),
+ 'weight' => 4,
+ ),
+ );
+
+ $subtotal = 0;
+ foreach (element_children($table) as $i) {
+ $subtotal += $table[$i]['#total'];
+
+ $table[$i]['remove']['#cell_attributes'] = array('align' => 'center', 'class' => 'remove');
+ $table[$i]['image']['#cell_attributes'] = array('class' => 'image');
+ $table[$i]['desc']['#cell_attributes'] = array('class' => 'desc');
+ $table[$i]['qty']['#cell_attributes'] = array('class' => 'qty');
+ $table[$i]['total']['#cell_attributes'] = array('class' => 'price');
+ $table[$i]['#attributes'] = array('valign' => 'top');
+ }
+
+ $context = array(
+ 'revision' => 'themed-original',
+ 'type' => 'amount',
+ );
+ $table[] = array(
+ 'total' => array(
+ '#value' => '<span id="subtotal-title">'. t('Subtotal:') .'</span> '. uc_price($subtotal, $context),
+ '#cell_attributes' => array(
+ 'colspan' => 'full',
+ 'class' => 'subtotal',
+ ),
+ ),
+ );
+
+ return $table;
+}
+
+
+/*******************************************************************************
+ * Module and Helper Functions
+ ******************************************************************************/
+
+/**
+ * Returns the URL redirect for the continue shopping element on the cart page.
+ *
+ * @param $unset
+ * TRUE or FALSE indicating whether or not to unset the last URL variable.
+ *
+ * @return
+ * The URL or Drupal path that will be used for the continue shopping element.
+ */
+function uc_cart_continue_shopping_url($unset = TRUE) {
+ $url = '';
+
+ // Use the last URL if enabled and available.
+ if (variable_get('uc_continue_shopping_use_last_url', TRUE) && isset($_SESSION['uc_cart_last_url'])) {
+ $url = $_SESSION['uc_cart_last_url'];
+ }
+
+ // If the URL is still empty, fall back to the default.
+ if (empty($url)) {
+ $url = variable_get('uc_continue_shopping_url', '');
+ }
+
+ // Unset the last URL if specified.
+ if ($unset) {
+ unset($_SESSION['uc_cart_last_url']);
+ }
+
+ return $url;
+}
+
+/**
+ * Completes a sale, including adjusting order status and creating user account.
+ *
+ * @param $order
+ * The order object that has just been completed.
+ * @param $login
+ * Whether or not to login a new user when this function is called.
+ *
+ * @return
+ * The HTML text of the default order completion page.
+ */
+function uc_cart_complete_sale($order, $login = FALSE) {
+ global $user;
+
+ // Ensure we have the latest order data.
+ $order->data = unserialize(db_result(db_query("SELECT data FROM {uc_orders} WHERE order_id = %d", $order->order_id)));
+
+ // Ensure that user creation and triggers are only run once.
+ if (empty($order->data['complete_sale'])) {
+ uc_cart_complete_sale_account($order);
+
+ // Store account data.
+ db_query("UPDATE {uc_orders} SET uid = %d, data = '%s' WHERE order_id = %d", $order->uid, serialize($order->data), $order->order_id);
+
+ // Move an order's status from "In Checkout" to "Pending"
+ $status = db_result(db_query("SELECT order_status FROM {uc_orders} WHERE order_id = %d", $order->order_id));
+ if (uc_order_status_data($status, 'state') == 'in_checkout') {
+ $status = uc_order_state_default('post_checkout');
+ if (uc_order_update_status($order->order_id, $status)) {
+ $order->order_status = $status;
+ }
+ }
+
+ // Invoke the checkout complete trigger and hook.
+ $account = user_load($order->uid);
+ module_invoke_all('uc_checkout_complete', $order, $account);
+ ca_pull_trigger('uc_checkout_complete', $order, $account);
+ }
+
+ $type = $order->data['complete_sale'];
+
+ // Log in new users, if requested.
+ if ($type == 'new_user' && $login && !$user->uid) {
+ $type = 'new_user_logged_in';
+ $user = user_load($order->uid);
+ }
+
+ $variables['!new_username'] = isset($order->data['new_user']['name']) ? $order->data['new_user']['name'] : '';
+ $variables['!new_password'] = isset($order->password) ? $order->password : t('Your password');
+ $messages = array(
+ 'uc_msg_order_submit' => uc_get_message('completion_message'),
+ 'uc_msg_order_' . $type => uc_get_message('completion_' . $type),
+ 'uc_msg_continue_shopping' => uc_get_message('continue_shopping'),
+ );
+ foreach ($messages as $id => &$message) {
+ $message = variable_get($id, $message);
+ $message = token_replace_multiple($message, array('global' => NULL, 'order' => $order));
+ if ($id == 'uc_msg_order_' . $type) {
+ $message = strtr($message, $variables);
+ }
+ $message = check_markup($message, variable_get($id . '_format', FILTER_FORMAT_DEFAULT), FALSE);
+ }
+ $output = implode('', $messages);
+
+ // Empty that cart...
+ uc_cart_empty(uc_cart_get_id(FALSE), 'checkout');
+
+ return theme('uc_cart_complete_sale', $output, $order);
+}
+
+/**
+ * Link a completed sale to a user.
+ *
+ * @param $order
+ * The order object that has just been completed.
+ */
+function uc_cart_complete_sale_account($order) {
+ // Order already has a user ID, so the user was logged in during checkout.
+ if ($order->uid) {
+ $order->data['complete_sale'] = 'logged_in';
+ return;
+ }
+
+ $result = db_query("SELECT uid FROM {users} WHERE LOWER(mail) = LOWER('%s')", $order->primary_email);
+
+ // Email address matches an existing account.
+ if ($account = db_fetch_object($result)) {
+ $order->uid = $account->uid;
+ $order->data['complete_sale'] = 'existing_user';
+ return;
+ }
+
+ // Set up a new user.
+ $fields = array(
+ 'name' => uc_store_email_to_username($order->primary_email),
+ 'mail' => $order->primary_email,
+ 'init' => $order->primary_email,
+ 'pass' => user_password(),
+ 'roles' => array(),
+ 'status' => variable_get('uc_new_customer_status_active', TRUE) ? 1 : 0,
+ );
+
+ // Override the username, if specified.
+ if (isset($order->data['new_user']['name'])) {
+ $fields['name'] = $order->data['new_user']['name'];
+ }
+
+ // Create the account.
+ $account = user_save('', $fields);
+
+ // Override the password, if specified.
+ if (isset($order->data['new_user']['hash'])) {
+ db_query("UPDATE {users} SET pass = '%s' WHERE uid = %d", $order->data['new_user']['hash'], $account->uid);
+ $account->password = t('Your password');
+ }
+ else {
+ $account->password = $fields['pass'];
+ $order->password = $fields['pass'];
+ }
+
+ // Send the customer their account details if enabled.
+ if (variable_get('uc_new_customer_email', TRUE)) {
+ drupal_mail('user', 'register_no_approval_required', $order->primary_email, uc_store_mail_recipient_language($order->primary_email), array('account' => $account), uc_store_email_from());
+ }
+
+ $order->uid = $account->uid;
+ $order->data['new_user']['name'] = $fields['name'];
+ $order->data['complete_sale'] = 'new_user';
+}
+
+/**
+ * Themes the sale completion page.
+ *
+ * @param $message
+ * Message containing order number info, account info, and link to continue
+ * shopping.
+ *
+ * @ingroup themeable
+ */
+function theme_uc_cart_complete_sale($message, $order = NULL) {
+ return $message;
+}
+
+/**
+ * Returns the unique cart_id of the user.
+ *
+ * @param $create
+ * Toggle auto creation of cart id.
+ *
+ * @return
+ * Cart id. If $create is FALSE will return FALSE if there is no cart id.
+ */
+function uc_cart_get_id($create = TRUE) {
+ global $user;
+
+ if ($user->uid) {
+ return $user->uid;
+ }
+ elseif (!isset($_SESSION['uc_cart_id']) && $create) {
+ $_SESSION['uc_cart_id'] = md5(uniqid(rand(), TRUE));
+ }
+
+ return isset($_SESSION['uc_cart_id']) ? $_SESSION['uc_cart_id'] : FALSE;
+}
+
+/**
+ * Grabs the items in a shopping cart for a user.
+ *
+ * @param $cid
+ * (optional) The cart ID to load, or NULL to load the current user's cart.
+ * @param $action
+ * (optional) Carts are statically cached by default. If set to "rebuild",
+ * the cache will be ignored and the cart reloaded from the database.
+ *
+ * @return
+ * An array of cart items.
+ */
+function uc_cart_get_contents($cid = NULL, $action = NULL) {
+ static $items = array();
+
+ $cid = $cid ? $cid : uc_cart_get_id(FALSE);
+
+ // If we didn't get a cid, return empty.
+ if (!$cid) {
+ return array();
+ }
+
+ if ($action == 'rebuild') {
+ unset($items[$cid]);
+ }
+
+ if (!isset($items[$cid])) {
+ $items[$cid] = array();
+ $result = db_query("SELECT * FROM {uc_cart_products} WHERE cart_id = '%s' ORDER BY cart_item_id ASC", $cid);
+
+ while ($item = db_fetch_object($result)) {
+ if ($item = uc_cart_get_item($item)) {
+ $items[$cid][] = $item;
+ }
+ }
+
+ // Allow other modules a chance to alter the fully loaded cart object.
+ drupal_alter('uc_cart', $items[$cid]);
+
+ // When there are no longer any items in the cart, the anonymous cart ID is no longer required.
+ // To guard against unsetting the session ID in the middle of an uc_cart_add_item() call, we only do this on rebuild
+ // See issue 858816 for details.
+ if ($action == 'rebuild' && empty($items[$cid]) && isset($_SESSION['uc_cart_id']) && $_SESSION['uc_cart_id'] == $cid) {
+ unset($_SESSION['uc_cart_id']);
+ }
+ }
+
+ return $items[$cid];
+}
+
+/**
+ * Returns the total number of items in the shopping cart.
+ *
+ * The total number of items in the cart isn't simply queried directly from the
+ * database, because when the shopping cart is loaded items may in fact be
+ * altered or removed. Hence we actually load the cart and tally up the total
+ * number of items from the fully loaded cart instead.
+ *
+ * @param $cid
+ * The cart ID of the shopping cart whose items we're totalling; defaults to
+ * the current user's cart.
+ *
+ * @return
+ * An integer representing the total number of items in the cart.
+ */
+function uc_cart_get_total_qty($cid = NULL) {
+
+ $qty = 0;
+
+ if (empty($cid)) {
+ $cid = uc_cart_get_id(FALSE);
+ }
+
+ if ($cid) {
+ foreach (uc_cart_get_contents($cid) as $item) {
+ $qty += $item->qty;
+ }
+ }
+
+ return $qty;
+}
+
+/**
+ * Allows us to get one single line item in a cart.
+ *
+ * @param $item
+ * Either an item row from the database, or the cart item ID to fetch.
+ *
+ * @return
+ * Fully loaded cart item or NULL if item not found
+ */
+function uc_cart_get_item($item) {
+ if (!is_object($item)) {
+ $item = db_fetch_object(db_query("SELECT * FROM {uc_cart_products} WHERE cart_item_id = '%d'", $item));
+ }
+
+ if (empty($item)) {
+ return;
+ }
+
+ $product = node_load($item->nid);
+ if (!$product) {
+ return;
+ }
+
+ $item->vid = $product->vid;
+ $item->title = $product->title;
+ $item->cost = $product->cost;
+ $item->price = $product->sell_price;
+ $item->weight = $product->weight;
+ $item->data = unserialize($item->data);
+ $item->module = $item->data['module'];
+ $item->model = $product->model;
+
+ // Invoke hook_cart_item() with $op = 'load' in enabled modules.
+ foreach (module_list() as $module) {
+ $func = $module .'_cart_item';
+ if (function_exists($func)) {
+ // $item must be passed by reference.
+ $func('load', $item);
+ }
+ }
+
+ return $item;
+}
+
+/**
+ * Updates a cart item.
+ *
+ * @param $item
+ * The loaded cart item.
+ *
+ * @return
+ * unknown_type
+ */
+function uc_cart_update_item($item) {
+ db_query("UPDATE {uc_cart_products} SET qty = %d, changed = UNIX_TIMESTAMP(), data = '%s' WHERE cart_item_id = %d",
+ $item->qty, serialize($item->data), $item->cart_item_id);
+}
+
+/**
+ * Adds an item to a user's cart.
+ */
+function uc_cart_add_item($nid, $qty = 1, $data = NULL, $cid = NULL, $msg = TRUE, $check_redirect = TRUE, $rebuild = TRUE) {
+ if (isset($_SESSION['cart_order'])) {
+ unset($_SESSION['cart_order']);
+ }
+
+ $cid = $cid ? $cid : uc_cart_get_id();
+ $node = node_load($nid);
+
+ if (is_null($data)) {
+ $data = array('module' => 'uc_product');
+ }
+ if (!isset($data['module'])) {
+ $data['module'] = 'uc_product';
+ }
+
+ if (!uc_product_is_product($node->type)) {
+ drupal_set_message(t('@title is not a product. Unable to add to cart.', array('@title' => $node->title)), 'error');
+ return;
+ }
+
+ $result = module_invoke_all('add_to_cart', $nid, $qty, $data);
+ if (is_array($result) && !empty($result)) {
+ foreach ($result as $row) {
+ if ($row['success'] === FALSE) {
+ if (isset($row['message']) && !empty($row['message'])) {
+ $message = $row['message'];
+ }
+ else {
+ $message = t('Sorry, that item is not available for purchase at this time.');
+ }
+ if (isset($row['silent']) && ($row['silent'] === TRUE)) {
+ if ($check_redirect) {
+ if (isset($_GET['destination'])) {
+ drupal_goto();
+ }
+ $_SESSION['uc_cart_last_url'] = uc_referer_uri();
+ $redirect = variable_get('uc_add_item_redirect', 'cart');
+ if ($redirect != '<none>') {
+ return $redirect;
+ }
+ else {
+ return uc_referer_uri();
+ }
+ }
+ }
+ else {
+ drupal_set_message($message, 'error');
+ }
+ return uc_referer_uri();
+ }
+ }
+ }
+
+ $item = db_fetch_object(db_query("SELECT * FROM {uc_cart_products} WHERE cart_id = '%s' AND nid = %d AND data = '%s'", $cid, $node->nid, serialize($data)));
+
+ // If the item isn't in the cart yet, add it.
+ if (is_null($item) || $item === FALSE) {
+ db_query("INSERT INTO {uc_cart_products} (cart_id, nid, qty, changed, data) VALUES ('%s', %d, %d, %d, '%s')", $cid, $node->nid, $qty, time(), serialize($data));
+ if ($msg) {
+ drupal_set_message(t('<strong>@product-title</strong> added to <a href="!url">your shopping cart</a>.', array('@product-title' => $node->title, '!url' => url('cart'))));
+ }
+ }
+ else {
+ // Update the item instead.
+ if ($msg) {
+ drupal_set_message(t('Your item(s) have been updated.'));
+ }
+ $qty += $item->qty;
+ module_invoke($data['module'], 'update_cart_item', $node->nid, $data, min($qty, 999999), $cid);
+ }
+
+ // If specified, rebuild the cached cart items array.
+ if ($rebuild) {
+ uc_cart_get_contents($cid, 'rebuild');
+ }
+
+ if ($check_redirect) {
+ if (isset($_GET['destination'])) {
+ drupal_goto();
+ }
+
+ $_SESSION['uc_cart_last_url'] = uc_referer_uri();
+ $redirect = variable_get('uc_add_item_redirect', 'cart');
+ if ($redirect != '<none>') {
+ return $redirect;
+ }
+ else {
+ return uc_referer_uri();
+ }
+ }
+}
+
+/**
+ * Removes an item from the cart.
+ *
+ * @param $nid
+ * The node ID of the item to remove.
+ * @param $cid
+ * The cart ID of the item to remove.
+ * @param $data
+ * The data array for the item to remove.
+ * @param $op
+ * The $op parameter to pass to hook_cart_item(), if not the default 'remove'.
+ */
+function uc_cart_remove_item($nid, $cid = NULL, $data = array(), $op = 'remove') {
+ if (empty($nid)) {
+ return;
+ }
+
+ $cart_id = !(is_null($cid) || empty($cid)) ? $cid : uc_cart_get_id();
+
+ // Invoke hook_cart_item() with $op = 'remove' in enabled modules.
+ $result = db_query("SELECT c.*, n.title, n.vid FROM {node} n INNER JOIN {uc_cart_products} c ON n.nid = c.nid WHERE c.cart_id = '%s' AND c.nid = %d AND c.data = '%s'", $cart_id, $nid, serialize($data));
+ if ($item = db_fetch_object($result)) {
+ foreach (module_list() as $module) {
+ $func = $module .'_cart_item';
+ if (function_exists($func)) {
+ // $item must be passed by reference.
+ $func($op, $item);
+ }
+ }
+ }
+
+ db_query("DELETE FROM {uc_cart_products} WHERE cart_id = '%s' AND nid = %d AND data = '%s'", $cart_id, $nid, serialize($data));
+}
+
+/**
+ * Updates the quantity of all the items in a cart object.
+ */
+function uc_cart_update_item_object($cart) {
+ if (is_object($cart)) {
+ foreach ($cart->items as $item) {
+ module_invoke($item['module'], 'update_cart_item', $item['nid'], unserialize($item['data']), $item['qty']);
+ }
+
+ // Rebuild the cached cart items.
+ uc_cart_get_contents(NULL, 'rebuild');
+ }
+}
+
+/**
+ * Empties a cart of its contents.
+ *
+ * @param $cart_id
+ * The ID of the cart.
+ * @param $op
+ * The $op parameter to pass to hook_cart_item(), if not the default 'remove'.
+ */
+function uc_cart_empty($cart_id, $op = 'remove') {
+ if (is_null($cart_id) || empty($cart_id)) {
+ return;
+ }
+
+ // Empty cart one item at a time. This will ensure the cart_item hook is fired with $op set to 'remove' for each item.
+ $items = uc_cart_get_contents($cart_id);
+ foreach($items as $item) {
+ uc_cart_remove_item($item->nid, $cart_id, $item->data, $op);
+ }
+
+ // Probably don't need this query, but it will ensure anything not removed with the above loop is removed here.
+ db_query("DELETE FROM {uc_cart_products} WHERE cart_id = '%s'", $cart_id);
+
+ // Remove cached cart.
+ uc_cart_get_contents($cart_id, 'rebuild');
+}
+
+/**
+ * Gets all of the enabled, sorted cart panes.
+ *
+ * @param $items
+ * The contents of the cart.
+ * @param $action
+ * If 'rebuild' is passed, the static pane cache is cleared.
+ */
+function uc_cart_cart_pane_list($items, $action = NULL) {
+ static $panes;
+
+ if (count($panes) > 0 && $action !== 'rebuild') {
+ return $panes;
+ }
+
+ $panes = module_invoke_all('cart_pane', $items);
+
+ // Allow other modules to alter the panes.
+ drupal_alter('cart_pane', $panes, $items);
+
+ if (!is_array($panes) || count($panes) == 0) {
+ return array();
+ }
+ foreach ($panes as $i => $value) {
+ $panes[$i]['enabled'] = variable_get('uc_cap_'. $panes[$i]['id'] .'_enabled', (!isset($panes[$i]['enabled']) ? TRUE : $panes[$i]['enabled']));
+ $panes[$i]['weight'] = variable_get('uc_cap_'. $panes[$i]['id'] .'_weight', (!isset($panes[$i]['weight']) ? 0 : $panes[$i]['weight']));
+ }
+ usort($panes, 'uc_weight_sort');
+
+ return $panes;
+}
+
+/**
+ * Determines whether a cart contains shippable items or not.
+ */
+function uc_cart_is_shippable($cart_id = NULL) {
+ $items = uc_cart_get_contents($cart_id);
+
+ foreach ($items as $item) {
+ if (uc_cart_product_is_shippable($item)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * Determines whether a product is shippable or not.
+ */
+function uc_cart_product_is_shippable($product) {
+ // Return FALSE if the product form specifies this as not shippable.
+ if ($product->data['shippable'] == FALSE) {
+ return FALSE;
+ }
+
+ $result = array();
+
+ // See if any other modules have a say in the matter...
+ foreach (module_list() as $module) {
+ $func = $module .'_cart_item';
+ if (function_exists($func)) {
+ // $product must be passed by reference.
+ $return = $func('can_ship', $product);
+
+ if (!is_null($return)) {
+ $result[] = $return;
+ }
+ }
+ }
+
+ // Return TRUE by default.
+ if (empty($result) || in_array(TRUE, $result)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * Removes panes from the list that match the given conditions.
+ *
+ * Returns a checkout pane array with panes filtered out that have key values
+ * matching the combinations in the $remove array.
+ */
+function uc_cart_filter_checkout_panes($panes, $remove = NULL) {
+ if (is_array($remove)) {
+ for ($i = 0, $j = count($panes); $i < $j; $i++) {
+ foreach ($remove as $key => $value) {
+ if (isset($panes[$i][$key]) && $panes[$i][$key] == $value) {
+ unset($panes[$i]);
+ }
+ }
+ }
+ }
+
+ return $panes;
+}
diff -Naur nohack/sites/all/modules/ubercart/uc_order/templates/packingslip.itpl.php dev/sites/all/modules/ubercart/uc_order/templates/packingslip.itpl.php
--- nohack/sites/all/modules/ubercart/uc_order/templates/packingslip.itpl.php 1970-01-01 07:00:00.000000000 +0700
+++ dev/sites/all/modules/ubercart/uc_order/templates/packingslip.itpl.php 2012-07-04 07:00:03.000000000 +0700
@@ -0,0 +1,140 @@
+<?php
+// $Id: packingslip.itpl.php,v 1.1.4.3 2009/11/28 21:19:15 longwave Exp $
+
+/**
+ * This file is the default packing slip template for Ubercart marketplace.
+ */
+?>
+
+<table width="95%" border="0" cellspacing="0" cellpadding="1" align="center" bgcolor="#006699" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td>
+ <table width="100%" border="0" cellspacing="0" cellpadding="5" align="center" bgcolor="#FFFFFF" style="font-family: verdana, arial, helvetica; font-size: small;">
+
+ <tr valign="top">
+ <td>
+ <table width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td>
+ [site-logo]
+ </td>
+ <td width="98%">
+ <div style="padding-left: 1em;">
+ <span style="font-size: large;">[store-name]</span><br/>
+ [site-slogan]
+ </div>
+ </td>
+ <td nowrap="nowrap">
+ [store-address]<br />[store-phone]
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ <tr valign="top">
+ <td>
+ <table cellpadding="4" cellspacing="0" border="0" width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td colspan="2">
+
+ <table width="100%" cellspacing="0" cellpadding="0" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <?php if (uc_order_is_shippable($order)) { ?>
+ <td valign="top" width="50%">
+ <b><?php echo t('Shipping Address:'); ?></b><br />
+ [order-shipping-address]<br />
+ <br />
+ </td>
+ <?php } ?>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" bgcolor="#EEEEEE">
+ <font color="#CC6600"><b><?php echo t('Shipment Summary:'); ?></b></font>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2">
+
+ <table border="0" cellpadding="1" cellspacing="0" width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Order #:'); ?></b>
+ </td>
+ <td width="98%">
+ [order-link]
+ </td>
+ </tr>
+
+ <?php if (uc_order_is_shippable($order)) { ?>
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Shipping Method:'); ?></b>
+ </td>
+ <td width="98%">
+ [order-shipping-method]
+ </td>
+ </tr>
+ <?php } ?>
+
+ <tr>
+ <td colspan="2">
+ <br /><b><?php echo t('Products in shipment:'); ?>&nbsp;</b>
+
+ <table width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+
+ <?php if (is_array($order->products)) {
+ foreach ($order->products as $product) { ?>
+ <tr>
+ <td valign="top" nowrap="nowrap">
+ <b><?php echo $product->qty; ?> x </b>
+ </td>
+ <td width="98%">
+ <b><?php echo $product->title; ?></b>
+ <br />
+ <?php echo t('SKU: ') . $product->model; ?><br />
+ <?php if (is_array($product->data['attributes']) && count($product->data['attributes']) > 0) {?>
+ <?php foreach ($product->data['attributes'] as $attribute => $option) {
+ echo '<li>'. t('@attribute: @options', array('@attribute' => $attribute, '@options' => implode(', ', (array)$option))) .'</li>';
+ } ?>
+ <?php } ?>
+ <br />
+ </td>
+ </tr>
+ <?php }
+ }?>
+
+ </td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2">
+ <hr noshade="noshade" size="1" />
+ <p><?php echo t('Thanks again for shopping with us. If you have questions about your order, please contact us.'); ?></p>
+ <p><?php echo t('Note: Please do not be alarmed if your complete order is not in this package or listed on this packing slip. We may ship multiple packages in multiple shipments to expedite the shipping process.'); ?></p>
+
+ <?php if ($store_footer) { ?>
+ <p><b>[store-link]</b><br /><b>[site-slogan]</b></p>
+ <?php } ?>
+ </td>
+ </tr>
+
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
+</td>
+</tr>
+</table>
diff -Naur nohack/sites/all/modules/ubercart/uc_order/templates/uc_order-admin.tpl.php_05_06_2012 dev/sites/all/modules/ubercart/uc_order/templates/uc_order-admin.tpl.php_05_06_2012
--- nohack/sites/all/modules/ubercart/uc_order/templates/uc_order-admin.tpl.php_05_06_2012 1970-01-01 07:00:00.000000000 +0700
+++ dev/sites/all/modules/ubercart/uc_order/templates/uc_order-admin.tpl.php_05_06_2012 2012-05-15 06:54:48.000000000 +0700
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * This file is the default admin notification template for Ubercart.
+ */
+?>
+
+<p>
+<?php echo t('Order number:'); ?> <?php echo $order_admin_link; ?><br />
+<?php echo t('Customer:'); ?> <?php echo $order_first_name; ?> <?php echo $order_last_name; ?> - <?php echo $order_email; ?><br />
+<?php echo t('Order total:'); ?> <?php echo $order_total; ?><br />
+<?php echo t('Shipping method:'); ?> <?php echo $order_shipping_method; ?>
+</p>
+
+<p>
+<?php echo t('Products:'); ?><br />
+<?php
+$context = array(
+ 'revision' => 'themed',
+ 'type' => 'order_product',
+ 'subject' => array(
+ 'order' => $order,
+ ),
+);
+foreach ($products as $product) {
+ $price_info = array(
+ 'price' => $product->price,
+ 'qty' => $product->qty,
+ );
+ $context['subject']['order_product'] = $product;
+?>
+- <?php echo $product->qty; ?> x <?php echo $product->title .' - '. uc_price($price_info, $context); ?><br />
+&nbsp;&nbsp;<?php echo t('SKU: ') . $product->model; ?><br />
+ <?php if (isset($product->data['attributes']) && is_array($product->data['attributes']) && count($product->data['attributes']) > 0) {?>
+ <?php foreach ($product->data['attributes'] as $attribute => $option) {
+ echo '&nbsp;&nbsp;'. t('@attribute: @options', array('@attribute' => $attribute, '@options' => implode(', ', (array)$option))) .'<br />';
+ } ?>
+ <?php } ?>
+<br />
+<?php } ?>
+</p>
+
+<p>
+<?php echo t('Order comments:'); ?><br />
+<?php echo $order_comments; ?>
+</p>
diff -Naur nohack/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php dev/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php
--- nohack/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php 2012-04-26 15:48:51.000000000 +0700
+++ dev/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php 2012-08-06 23:12:06.000000000 +0700
@@ -231,7 +231,15 @@
<b><?php echo $product->qty; ?> x </b>
</td>
<td width="98%">
- <b><?php echo $product->title .' - '. uc_price($price_info, $context); ?></b>
+ <b><?php echo $product->title .' - '. uc_price($price_info, $context); ?>
+ <?php
+ $node_obj = node_load($product->nid);
+ foreach($node_obj->og_groups as $groups){
+ $group_obj = node_load($groups);
+ }
+ echo "<br /><b style='padding-top:3px;'>Shop Owner</b><br />".l($group_obj->title, 'node/'.$group_obj->nid);
+ ?>
+ </b>
<?php if ($product->qty > 1) {
$price_info['qty'] = 1;
echo t('(!price each)', array('!price' => uc_price($price_info, $context)));
diff -Naur nohack/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php_05_06_2012 dev/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php_05_06_2012
--- nohack/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php_05_06_2012 1970-01-01 07:00:00.000000000 +0700
+++ dev/sites/all/modules/ubercart/uc_order/templates/uc_order-customer.tpl.php_05_06_2012 2012-05-15 06:54:49.000000000 +0700
@@ -0,0 +1,290 @@
+<?php
+
+/**
+ * @file
+ * This file is the default customer invoice template for Ubercart.
+ */
+?>
+
+<table width="95%" border="0" cellspacing="0" cellpadding="1" align="center" bgcolor="#006699" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td>
+ <table width="100%" border="0" cellspacing="0" cellpadding="5" align="center" bgcolor="#FFFFFF" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <?php if ($business_header) { ?>
+ <tr valign="top">
+ <td>
+ <table width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td>
+ <?php echo $site_logo; ?>
+ </td>
+ <td width="98%">
+ <div style="padding-left: 1em;">
+ <span style="font-size: large;"><?php echo $store_name; ?></span><br />
+ <?php echo $site_slogan; ?>
+ </div>
+ </td>
+ <td nowrap="nowrap">
+ <?php echo $store_address; ?><br /><?php echo $store_phone; ?>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <?php } ?>
+
+ <tr valign="top">
+ <td>
+
+ <?php if ($thank_you_message) { ?>
+ <p><b><?php echo t('Thanks for your order, !order_first_name!', array('!order_first_name' => $order_first_name)); ?></b></p>
+
+ <?php if (isset($order->data['new_user'])) { ?>
+ <p><b><?php echo t('An account has been created for you with the following details:'); ?></b></p>
+ <p><b><?php echo t('Username:'); ?></b> <?php echo $new_username; ?><br />
+ <b><?php echo t('Password:'); ?></b> <?php echo $new_password; ?></p>
+ <?php } ?>
+
+ <p><b><?php echo t('Want to manage your order online?'); ?></b><br />
+ <?php echo t('If you need to check the status of your order, please visit our home page at !store_link and click on "My account" in the menu or login with the following link:', array('!store_link' => $store_link)); ?>
+ <br /><br /><?php echo $site_login; ?></p>
+ <?php } ?>
+
+ <table cellpadding="4" cellspacing="0" border="0" width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td colspan="2" bgcolor="#006699" style="color: white;">
+ <b><?php echo t('Purchasing Information:'); ?></b>
+ </td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('E-mail Address:'); ?></b>
+ </td>
+ <td width="98%">
+ <?php echo $order_email; ?>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2">
+
+ <table width="100%" cellspacing="0" cellpadding="0" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td valign="top" width="50%">
+ <b><?php echo t('Billing Address:'); ?></b><br />
+ <?php echo $order_billing_address; ?><br />
+ <br />
+ <b><?php echo t('Billing Phone:'); ?></b><br />
+ <?php echo $order_billing_phone; ?><br />
+ </td>
+ <?php if (uc_order_is_shippable($order)) { ?>
+ <td valign="top" width="50%">
+ <b><?php echo t('Shipping Address:'); ?></b><br />
+ <?php echo $order_shipping_address; ?><br />
+ <br />
+ <b><?php echo t('Shipping Phone:'); ?></b><br />
+ <?php echo $order_shipping_phone; ?><br />
+ </td>
+ <?php } ?>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Order Grand Total:'); ?></b>
+ </td>
+ <td width="98%">
+ <b><?php echo $order_total; ?></b>
+ </td>
+ </tr>
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Payment Method:'); ?></b>
+ </td>
+ <td width="98%">
+ <?php echo $order_payment_method; ?>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2" bgcolor="#006699" style="color: white;">
+ <b><?php echo t('Order Summary:'); ?></b>
+ </td>
+ </tr>
+
+ <?php if (uc_order_is_shippable($order)) { ?>
+ <tr>
+ <td colspan="2" bgcolor="#EEEEEE">
+ <font color="#CC6600"><b><?php echo t('Shipping Details:'); ?></b></font>
+ </td>
+ </tr>
+ <?php } ?>
+
+ <tr>
+ <td colspan="2">
+
+ <table border="0" cellpadding="1" cellspacing="0" width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Order #:'); ?></b>
+ </td>
+ <td width="98%">
+ <?php echo $order_link; ?>
+ </td>
+ </tr>
+
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Order Date: '); ?></b>
+ </td>
+ <td width="98%">
+ <?php echo $order_date_created; ?>
+ </td>
+ </tr>
+
+ <?php if ($shipping_method && uc_order_is_shippable($order)) { ?>
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Shipping Method:'); ?></b>
+ </td>
+ <td width="98%">
+ <?php echo $order_shipping_method; ?>
+ </td>
+ </tr>
+ <?php } ?>
+
+ <tr>
+ <td nowrap="nowrap">
+ <?php echo t('Products Subtotal:'); ?>&nbsp;
+ </td>
+ <td width="98%">
+ <?php echo $order_subtotal; ?>
+ </td>
+ </tr>
+
+ <?php
+ $context = array(
+ 'revision' => 'themed',
+ 'type' => 'line_item',
+ 'subject' => array(
+ 'order' => $order,
+ ),
+ );
+ foreach ($line_items as $item) {
+ if ($item['line_item_id'] == 'subtotal' || $item['line_item_id'] == 'total') {
+ continue;
+ }?>
+
+ <tr>
+ <td nowrap="nowrap">
+ <?php echo $item['title']; ?>:
+ </td>
+ <td>
+ <?php
+ $context['subject']['line_item'] = $item;
+ echo uc_price($item['amount'], $context);
+ ?>
+ </td>
+ </tr>
+
+ <?php } ?>
+
+ <tr>
+ <td>&nbsp;</td>
+ <td>------</td>
+ </tr>
+
+ <tr>
+ <td nowrap="nowrap">
+ <b><?php echo t('Total for this Order:'); ?>&nbsp;</b>
+ </td>
+ <td>
+ <b><?php echo $order_total; ?></b>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2">
+ <br /><br /><b><?php echo t('Products on order:'); ?>&nbsp;</b>
+
+ <table width="100%" style="font-family: verdana, arial, helvetica; font-size: small;">
+
+ <?php if (is_array($order->products)) {
+ $context = array(
+ 'revision' => 'formatted',
+ 'type' => 'order_product',
+ 'subject' => array(
+ 'order' => $order,
+ ),
+ );
+ foreach ($order->products as $product) {
+ $price_info = array(
+ 'price' => $product->price,
+ 'qty' => $product->qty,
+ );
+ $context['subject']['order_product'] = $product;
+ $context['subject']['node'] = node_load($product->nid);
+ ?>
+ <tr>
+ <td valign="top" nowrap="nowrap">
+ <b><?php echo $product->qty; ?> x </b>
+ </td>
+ <td width="98%">
+ <b><?php echo $product->title .' - '. uc_price($price_info, $context); ?></b>
+ <?php if ($product->qty > 1) {
+ $price_info['qty'] = 1;
+ echo t('(!price each)', array('!price' => uc_price($price_info, $context)));
+ } ?>
+ <br />
+ <?php echo t('SKU: ') . $product->model; ?><br />
+ <?php if (isset($product->data['attributes']) && is_array($product->data['attributes']) && count($product->data['attributes']) > 0) {?>
+ <?php foreach ($product->data['attributes'] as $attribute => $option) {
+ echo '<li>'. t('@attribute: @options', array('@attribute' => $attribute, '@options' => implode(', ', (array)$option))) .'</li>';
+ } ?>
+ <?php } ?>
+ <br />
+ </td>
+ </tr>
+ <?php }
+ }?>
+ </table>
+
+ </td>
+ </tr>
+ </table>
+
+ </td>
+ </tr>
+
+ <?php if ($help_text || $email_text || $store_footer) { ?>
+ <tr>
+ <td colspan="2">
+ <hr noshade="noshade" size="1" /><br />
+
+ <?php if ($help_text) { ?>
+ <p><b><?php echo t('Where can I get help with reviewing my order?'); ?></b><br />
+ <?php echo t('To learn more about managing your orders on !store_link, please visit our <a href="!store_help_url">help page</a>.', array('!store_link' => $store_link, '!store_help_url' => $store_help_url)); ?>
+ <br /></p>
+ <?php } ?>
+
+ <?php if ($email_text) { ?>
+ <p><?php echo t('Please note: This e-mail message is an automated notification. Please do not reply to this message.'); ?></p>
+
+ <p><?php echo t('Thanks again for shopping with us.'); ?></p>
+ <?php } ?>
+
+ <?php if ($store_footer) { ?>
+ <p><b><?php echo $store_link; ?></b><br /><b><?php echo $site_slogan; ?></b></p>
+ <?php } ?>
+ </td>
+ </tr>
+ <?php } ?>
+
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+</table>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment