1) { $result[] = array( 'success' => FALSE, 'message' => t('Sorry, you can only add one of those at a time.'), ); } return $result; } /** * Adds extra information to a cart item's "data" array. * * This is effectively the submit handler of any alterations to the Add to Cart * form. It provides a standard way to store the extra information so that it * can be used by hook_add_to_cart(). * * @param $form_values * The values submitted to the Add to Cart form. * * @return * An array of data to be merged into the item added to the cart. */ function hook_uc_add_to_cart_data($form_values) { $node = node_load($form_values['nid']); return array('module' => 'uc_product', 'shippable' => $node->shippable); } /** * Controls the display of an item in the cart. * * Product type modules allow the creation of nodes that can be added to the * cart. The cart determines how they are displayed through this hook. This is * especially important for product kits, because it may be displayed as a * single unit in the cart even though it is represented as several items. * * @param $item * The item in the cart to display. * * @return * A form array containing the following elements: * - "nid" * - #type: value * - #value: The node id of the $item. * - "module" * - #type: value * - #value: The module implementing this hook and the node represented by * $item. * - "remove" * - #type: checkbox * - #value: If selected, removes the $item from the cart. * - "description" * - #type: markup * - #value: Themed markup (usually an unordered list) displaying extra information. * - "title" * - #type: markup * - #value: The displayed title of the $item. * - "#total" * - "type": float * - "value": Numeric price of $item. Notice the '#' signifying that this is * not a form element but just a value stored in the form array. * - "data" * - #type: hidden * - #value: The serialized $item->data. * - "qty" * - #type: textfield * - #value: The quantity of $item in the cart. When "Update cart" is * clicked, the customer's input is saved to the cart. */ function hook_uc_cart_display($item) { $node = node_load($item->nid); $element = array(); $element['nid'] = array('#type' => 'value', '#value' => $node->nid); $element['module'] = array('#type' => 'value', '#value' => 'uc_product'); $element['remove'] = array('#type' => 'checkbox'); $element['title'] = array( '#markup' => node_access('view', $node) ? l($item->title, 'node/' . $node->nid) : check_plain($item->title), ); $element['#total'] = $item->price * $item->qty; $element['data'] = array('#type' => 'hidden', '#value' => serialize($item->data)); $element['qty'] = array( '#type' => 'textfield', '#default_value' => $item->qty, '#size' => 5, '#maxlength' => 6 ); if ($description = uc_product_get_description($item)) { $element['description'] = array('#markup' => $description); } return $element; } /** * Adds extra data about an item in the cart. * * Products that are added to a customer's cart are referred as items until the * sale is completed. Just think of a grocery store having a bunch of products * on the shelves but putting a sign over the express lane saying "15 Items or * Less." hook_cart_item() is in charge of acting on items at various times like * when they are being added to a cart, saved, loaded, and checked out. * * Here's the rationale for this hook: Products may change on a live site during * a price increase or change to attribute adjustments. If a user has previously * added an item to their cart, when they go to checkout or view their cart * screen we want the latest pricing and model numbers to show. So, the * essential product information is stored in the cart, but when the items in * a cart are loaded, modules are given a chance to adjust the data against * the latest settings. * * @param $op * The action that is occurring. Possible values: * - "load" - Passed for each item when a cart is being loaded in the function * uc_cart_get_contents(). This gives modules the chance to tweak * information for items when the cart is being loaded prior to being * added to an order. No return value is expected. * - "view" - Passed for each item when it is about to be displayed on the * cart page. Modifications made affect only displayed information and are * not used in any calculations. * - "can_ship" - Passed when a cart is being scanned for items that are not * shippable items. Ubercart will bypass cart and checkout operations * specifically related to tangible products if nothing in the cart is * shippable. hook_cart_item functions that check for this op are expected * to return TRUE or FALSE based on whether a product is shippable or not. * - "remove" - Passed when an item is removed from the cart. * - "checkout" - Passed for each item when the cart is being emptied for * checkout. * * @return * No return value for load or view. TRUE or FALSE for can_ship. */ function hook_uc_cart_item($op, &$item) { switch ($op) { case 'load': $term = array_shift(taxonomy_node_get_terms_by_vocabulary($item->nid, variable_get('uc_manufacturer_vid', 0))); $item->manufacturer = $term->name; break; } } /** * Registers callbacks for a cart pane. * * The default cart view page displays a table of the cart contents and a few * simple form features to manage the cart contents. For a module to add * information to this page, it must use hook_cart_pane to define extra panes * that may be ordered to appear above or below the default information. * * @param $items * The current contents of the shopping cart. * * @return * The function is expected to return an array of pane arrays with the * following keys: * - "id" * - type: string * - value: The internal ID of the pane, using a-z, 0-9, and - or _. * - "title" * - type: string * - value: The name of the cart pane displayed to the user. Use t(). * - "enabled" * - type: boolean * - value: Whether the pane is enabled by default or not. (Defaults to TRUE.) * - "weight" * - type: integer * - value: The weight of the pane to determine its display order. (Defaults * to 0.) * - "body" * - type: array * - value: The body of the pane to be rendered on the cart view screen. * * The body gets printed to the screen if it is on the cart view page. For the * settings page, the body field is ignored. You may want your function to * check for a NULL argument before processing any queries or foreach() loops. */ function hook_uc_cart_pane($items) { $body = array(); if (!is_null($items)) { $body = drupal_get_form('uc_cart_view_form', $items) + array( '#prefix' => '
', '#suffix' => '
', ); } $panes[] = array( 'id' => 'cart_form', 'title' => t('Default cart form'), 'enabled' => TRUE, 'weight' => 0, 'body' => $body, ); return $panes; } /** * Alter cart pane definitions. * * @param $panes * The array of pane information in the format defined in hook_uc_cart_pane(), * passed by reference. * * @param $items * The array of item information. */ function hook_uc_cart_pane_alter(&$panes, $items) { foreach ($panes as &$pane) { if ($pane['id'] == 'cart') { $pane['body'] = drupal_get_form('my_custom_pane_form_builder', $items); } } } /** * Take action when checkout is completed. * * @param $order * The resulting order object from the completed checkout. * @param $account * The customer that completed checkout, either the current user, or the * account created for an anonymous customer. */ function hook_uc_checkout_complete($order, $account) { // Get previous records of customer purchases. $nids = array(); $result = db_query("SELECT uid, nid, qty FROM {uc_customer_purchases} WHERE uid = :uid", array(':uid' => $account->uid)); foreach ($result as $record) { $nids[$record->nid] = $record->qty; } // Update records with new data. $record = array('uid' => $account->uid); foreach ($order->products as $product) { $record['nid'] = $product->nid; if (isset($nids[$product->nid])) { $record['qty'] = $nids[$product->nid] + $product->qty; db_write_record($record, 'uc_customer_purchases', array('uid', 'nid')); } else { $record['qty'] = $product->qty; db_write_record($record, 'uc_customer_purchases'); } } } /** * Registers callbacks for a checkout pane. * * The checkout screen for Ubercart is a compilation of enabled checkout panes. * A checkout pane can be used to display order information, collect data from * the customer, or interact with other panes. Panes are defined in enabled * modules with hook_checkout_pane() and displayed and processed through * specified callback functions. Some of the settings for each pane are * configurable from the checkout settings page with defaults being specified * in the hooks. * * The default panes are defined in uc_cart.module in the function * uc_cart_checkout_pane(). These include panes to display the contents of the * shopping cart and to collect essential site user information, a shipping * address, a payment address, and order comments. Other included modules offer * panes for shipping and payment purposes as well. * * @return * An array of checkout pane arrays using the following keys: * - id: * - type: string * - value: The internal ID of the checkout pane, using a-z, 0-9, and - or _. * - title: * - type: string * - value:The name of the pane as it appears on the checkout form. * - desc: * - type: string * - value: A short description of the pane for the admin pages. * - callback: * - type: string * - value: The name of the callback function for this pane. View * @link http://www.ubercart.org/docs/developer/245/checkout this page @endlink * for more documentation and examples of checkout pane callbacks. * - weight: * - type: integer * - value: Default weight of the pane, defining its order on the checkout form. * - enabled: * - type: boolean * - value: Optional. Whether or not the pane is enabled by default. Defaults * to TRUE. * - process: * - type: boolean * - value: Optional. Whether or not this pane needs to be processed when the * checkout form is submitted. Defaults to TRUE. * - collapsible: * - type: boolean * - value: Optional. Whether or not this pane is displayed as a collapsible * fieldset. Defaults to TRUE. * - shippable: * - type: boolean * - value: Optional. If TRUE, the pane is only shown if the cart is shippable. * Defaults to NULL. */ function hook_uc_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, ); return $panes; } /** * Builds and proceses a pane defined by hook_uc_checkout_pane(). * * @param string $op * The operation the pane is performing. Possible values are "view", "process", * "review", and "settings". * @param UcOrder $order * The order being viewed or edited. * @param array $form * The order's edit form. NULL for non-edit ops. * @param array &$form_state * The form state array of the edit form. NULL for non-edit ops. * * @return * Varies according to the value of $op: * - view: An array with two keys, "contents" and an optional "description". * "contents" is a form array to collect the checkout data for the pane. The * description provides help text for the pane as a whole. * - process: A boolean indicating that checkout should continue. During this * op, $order should be modified with the values in $form_state['values']['panes'][PANE_ID]. * - review: An array containing review sections. A review section contains * "title" and "data" keys which have HTML to be displayed on the checkout * review page. * - settings: A settings form which can be used with system_settings_form(). */ function uc_checkout_pane_callback($op, $order, $form = NULL, &$form_state = NULL) { // uc_checkout_pane_comments() switch ($op) { case 'view': $description = t('Use this area for special instructions or questions regarding your order.'); if (!empty($order->order_id)) { $default = db_query("SELECT message FROM {uc_order_comments} WHERE order_id = :id", array(':id' => $order->order_id))->fetchField(); } else { $default = NULL; } $contents['comments'] = array( '#type' => 'textarea', '#title' => t('Order comments'), '#default_value' => $default, ); return array('description' => $description, 'contents' => $contents); case 'process': if (strlen($form_state['values']['panes']['comments']['comments']) > 0) { db_delete('uc_order_comments') ->condition('order_id', $order->order_id) ->execute(); uc_order_comment_save($order->order_id, 0, $form_state['values']['panes']['comments']['comments'], 'order', uc_order_state_default('post_checkout'), TRUE); } return TRUE; case 'review': $review = NULL; $result = db_query("SELECT message FROM {uc_order_comments} WHERE order_id = :id", array(':id' => $order->order_id)); if ($comment = $result->fetchObject()) { $review[] = array('title' => t('Comment'), 'data' => check_plain($comment->message)); } return $review; } } /** * Alters checkout pane definitions. * * @param $panes * Array with the panes information as defined in hook_uc_checkout_pane(), * passed by reference. */ function hook_uc_checkout_pane_alter(&$panes) { foreach ($panes as &$pane) { if ($pane['id'] == 'cart') { $pane['callback'] = 'my_custom_module_callback'; } } } /** * Handles requests to update a cart item. * * @param $nid * Node id of the cart item. * @param $data * Array of extra information about the item. * @param $qty * The quantity of this item in the cart. * @param $cid * The cart id. Defaults to NULL, which indicates that the current user's cart * should be retrieved with uc_cart_get_id(). */ function hook_uc_update_cart_item($nid, $data = array(), $qty, $cid = NULL) { if (!$nid) return NULL; $cid = !(is_null($cid) || empty($cid)) ? $cid : uc_cart_get_id(); if ($qty < 1) { uc_cart_remove_item($nid, $cid, $data); } else { db_update('uc_cart_products') ->fields(array( 'qty' => $qty, 'changed' => REQUEST_TIME, )) ->condition('nid', $nid) ->condition('cart_id', $cid) ->condition('data', serialize($data)) ->execute(); } // Rebuild the items hash uc_cart_get_contents(NULL, 'rebuild'); if (!strpos(request_uri(), 'cart', -4)) { drupal_set_message(t('Your item(s) have been updated.')); } } /** * @} End of "addtogroup hooks". */