/[drupal]/contributions/modules/ubercart/docs/hooks.php
ViewVC logotype

Contents of /contributions/modules/ubercart/docs/hooks.php

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download) (as text)
Thu Jul 10 12:40:56 2008 UTC (16 months, 2 weeks ago) by islandusurper
Branch: MAIN
CVS Tags: DRUPAL-5--1-2, HEAD
Branch point for: DRUPAL-5, DRUPAL-6--2
File MIME type: text/x-php
Begin the Ubercart 6.x-2.x branch.
1 <?php
2 // $Id:$
3
4 /**
5 * @file
6 * These are the hooks that are invoked by the Übercart core.
7 *
8 * Core hooks are typically called in all modules at once using
9 * module_invoke_all().
10 */
11
12 /**
13 * @addtogroup hooks
14 * @{
15 */
16
17 /**
18 * Do extra processing when an item is added to the shopping cart.
19 *
20 * Some modules need to be able to hook into the process of adding items to a
21 * cart. For example, an inventory system may need to check stock levels and
22 * prevent an out of stock item from being added to a customer's cart. This hook
23 * lets developers squeeze right in at the end of the process after the product
24 * information is all loaded and the product is about to be added to the cart.
25 * In the event that a product should not be added to the cart, you simply have
26 * to return a failure message described below. This hook may also be used simply
27 * to perform some routine action when products are added to the cart.
28 *
29 * @param $nid
30 * The node ID of the product
31 * @param $qty
32 * The quantity being added
33 * @param $data
34 * The data array, including attributes and model number adjustments
35 * @return
36 * The function can use this data to whatever purpose to see if the item can
37 * be added to the cart or not. The function should return an array containing
38 * the result array. (This is due to the nature of Drupal's module_invoke_all()
39 * function. You must return an array within an array or other module data will
40 * end up getting ignored.) At this moment, there are only three keys:
41 * - "success": TRUE or FALSE for whether the specified quantity of the item
42 * may be added to the cart or not; defaults to TRUE.
43 * - "message": the fail message to display in the event of a failure; if
44 * omitted, Ubercart will display a default fail message.
45 * - "silent": return TRUE to suppress the display of any messages; useful
46 * when a module simply needs to do some other processing during an add to
47 * cart or fail silently.
48 */
49 function hook_add_to_cart($nid, $qty, $data) {
50 if ($qty > 1) {
51 $result[] = array(
52 'success' => FALSE,
53 'message' => t('Sorry, you can only add one of those at a time.'),
54 );
55 }
56 return $result;
57 }
58
59 /**
60 * Add extra information to a cart item's "data" array.
61 *
62 * This is effectively the submit handler of any alterations to the Add to Cart
63 * form. It provides a standard way to store the extra information so that it
64 * can be used by hook_add_to_cart().
65 *
66 * @param $form_values
67 * The values submitted to the Add to Cart form.
68 * @return
69 * An array of data to be merged into the item added to the cart.
70 */
71 function hook_add_to_cart_data($form_values) {
72 $node = node_load($form_values['nid']);
73 return array('module' => 'uc_product', 'shippable' => $node->shippable);
74 }
75
76 /**
77 * Control the display of an item in the cart.
78 *
79 * Product type modules allow the creation of nodes that can be added to the
80 * cart. The cart determines how they are displayed through this hook. This is
81 * especially important for product kits, because it may be displayed as a single
82 * unit in the cart even though it is represented as several items.
83 *
84 * @param $item
85 * The item in the cart to display.
86 * @return
87 * A form array containing the following elements:
88 * - "nid"
89 * - #type: value
90 * - #value: The node id of the $item.
91 * - "module"
92 * - #type: value
93 * - #value: The module implementing this hook and the node represented by
94 * $item.
95 * - "remove"
96 * - #type: checkbox
97 * - #value: If selected, removes the $item from the cart.
98 * - "options"
99 * - #type: markup
100 * - #value: Themed markup (usually an unordered list) displaying extra information.
101 * - "title"
102 * - #type: markup
103 * - #value: The displayed title of the $item.
104 * - "#total"
105 * - "type": float
106 * - "value": Numeric price of $item. Notice the '#' signifying that this is
107 * not a form element but just a value stored in the form array.
108 * - "data"
109 * - #type: hidden
110 * - #value: The serialized $item->data.
111 * - "qty"
112 * - #type: textfield
113 * - #value: The quantity of $item in the cart. When "Update cart" is clicked,
114 * the customer's input is saved to the cart.
115 */
116 function hook_cart_display($item) {
117 $node = node_load($item->nid);
118 $element = array();
119 $element['nid'] = array('#type' => 'value', '#value' => $node->nid);
120 $element['module'] = array('#type' => 'value', '#value' => 'uc_product');
121 $element['remove'] = array('#type' => 'checkbox');
122 $op_names = '';
123 if (module_exists('uc_attribute')){
124 $op_names = "<ul class=\"cart-options\">\n";
125 foreach ($item->options as $option){
126 $op_names .= '<li>'. $option['attribute'] .': '. $option['name'] ."</li>\n";
127 }
128 $op_names .= "</ul>\n";
129 }
130 $element['options'] = array('#value' => $op_names);
131 $element['title'] = array(
132 '#value' => l($node->title, 'node/'. $node->nid),
133 );
134 $element['#total'] = $item->price * $item->qty;
135 $element['data'] = array('#type' => 'hidden', '#value' => serialize($item->data));
136 $element['qty'] = array(
137 '#type' => 'textfield',
138 '#default_value' => $item->qty,
139 '#size' => 3,
140 '#maxlength' => 3
141 );
142 return $element;
143 }
144
145 /**
146 * Add extra data about an item in the cart.
147 *
148 * Products that are added to a customer's cart are referred as items until the
149 * sale is completed. Just think of a grocery store having a bunch of products
150 * on the shelves but putting a sign over the express lane saying "15 Items or
151 * Less." hook_cart_item() is in charge of acting on items at various times like
152 * when they are being added to a cart, saved, loaded, and checked out.
153 *
154 * Here's the rationale for this hook: Products may change on a live site during
155 * a price increase or change to attribute adjustments. If a user has previously
156 * added an item to their cart, when they go to checkout or view their cart
157 * screen we want the latest pricing and model numbers to show. So, the essential
158 * product information is stored in the cart, but when the items in a cart are
159 * loaded, modules are given a chance to adjust the data against the latest settings.
160 *
161 * @param $op
162 * The action that is occurring. Possible values:
163 * - "load" - Passed for each item when a cart is being loaded in the function
164 * uc_cart_get_contents(). This gives modules the chance to tweak information
165 * for items when the cart is being loaded prior to being view or added to
166 * an order. No return value is expected.
167 * - "can_ship" - Passed when a cart is being scanned for items that are not
168 * shippable items. Übercart will bypass cart and checkout operations
169 * specifically related to tangible products if nothing in the cart is
170 * shippable. hook_cart_item functions that check for this op are expected
171 * to return TRUE or FALSE based on whether a product is shippable or not.
172 * @return
173 * No return value for load.
174 * TRUE or FALSE for can_ship.
175 */
176 function hook_cart_item($op, &$item) {
177 switch ($op) {
178 case 'load':
179 $term = array_shift(taxonomy_node_get_terms_by_vocabulary($item->nid, variable_get('uc_manufacturer_vid', 0)));
180 $arg1->manufacturer = $term->name;
181 break;
182 }
183 }
184
185 /**
186 * Register callbacks for a cart pane.
187 *
188 * The default cart view page displays a table of the cart contents and a few
189 * simple form features to manage the cart contents. For a module to add
190 * information to this page, it must use hook_cart_pane to define extra panes
191 * that may be ordered to appear above or below the default information.
192 *
193 * @param $items
194 * The current contents of the shopping cart.
195 * @return
196 * The function is expected to return an array of pane arrays with the following
197 * keys:
198 * - "id"
199 * - type: string
200 * - value: The internal ID of the pane, using a-z, 0-9, and - or _.
201 * - "title"
202 * - type: string
203 * - value: The name of the cart pane displayed to the user. Use t().
204 * - "enabled"
205 * - type: boolean
206 * - value: Whether the pane is enabled by default or not. (Defaults to TRUE.)
207 * - "weight"
208 * - type: integer
209 * - value: The weight of the pane to determine its display order. (Defaults
210 * to 0.)
211 * - "body"
212 * - type: string
213 * - value: The body of the pane when rendered on the cart view screen.
214 *
215 * The body gets printed to the screen if it is on the cart view page. For the
216 * settings page, the body field is ignored. You may want your function to check
217 * for a NULL argument before processing any queries or foreach() loops.
218 */
219 function hook_cart_pane($items) {
220 $panes[] = array(
221 'id' => 'cart_form',
222 'title' => t('Default cart form'),
223 'enabled' => TRUE,
224 'weight' => 0,
225 'body' => !is_null($items) ? drupal_get_form('uc_cart_view_form', $items) : '',
226 );
227
228 return $panes;
229 }
230
231 /**
232 * Register callbacks for a checkout pane.
233 *
234 * The checkout screen for Ubercart is a compilation of enabled checkout panes.
235 * A checkout pane can be used to display order information, collect data from
236 * the customer, or interact with other panes. Panes are defined in enabled modules
237 * with hook_checkout_pane() and displayed and processed through specified callback
238 * functions. Some of the settings for each pane are configurable from the checkout
239 * settings page with defaults being specified in the hooks.
240 *
241 * The default panes are defined in uc_cart.module in the function
242 * uc_cart_checkout_pane(). These include panes to display the contents of the
243 * shopping cart and to collect essential site user information, a shipping address,
244 * a payment address, and order comments. Other included modules offer panes for
245 * shipping and payment purposes as well.
246 *
247 * @return
248 * An array of checkout pane arrays using the following keys:
249 * - "id"
250 * - type: string
251 * - value: The internal ID of the checkout pane, using a-z, 0-9, and - or _.
252 * - "title"
253 * - type: string
254 * - value:The name of the pane as it appears on the checkout form.
255 * - "desc"
256 * - type: string
257 * - value: A short description of the pane for the admin pages.
258 * - "callback"
259 * - type: string
260 * - value: The name of the callback function for this pane. View
261 * @link http://www.ubercart.org/docs/developer/245/checkout this page @endlink
262 * for more documentation and examples of checkout pane callbacks.
263 * - "weight"
264 * - type: integer
265 * - value: Default weight of the pane, defining its order on the checkout form.
266 * - "enabled"
267 * - type: boolean
268 * - value: Optional. Whether or not the pane is enabled by default. Defaults
269 * to TRUE.
270 * - "process"
271 * - type: boolean
272 * - value: Optional. Whether or not this pane needs to be processed when the
273 * checkout form is submitted. Defaults to TRUE.
274 * - "collapsible"
275 * - type: boolean
276 * - value: Optional. Whether or not this pane is displayed as a collapsible
277 * fieldset. Defaults to TRUE.
278 */
279 function hook_checkout_pane() {
280 $panes[] = array(
281 'id' => 'cart',
282 'callback' => 'uc_checkout_pane_cart',
283 'title' => t('Cart Contents'),
284 'desc' => t("Display the contents of a customer's shopping cart."),
285 'weight' => 1,
286 'process' => FALSE,
287 'collapsible' => FALSE,
288 );
289 return $panes;
290 }
291
292 /**
293 * Give clearance to a user to download a file.
294 *
295 * By default the uc_file module can implement 3 restrictions on downloads: by
296 * number of IP addresses downloaded from, by number of downloads, and by a set
297 * expiration date. Developers wishing to add further restrictions can do so by
298 * implementing this hook. After the 3 aforementioned restrictions are checked,
299 * the uc_file module will check for implementations of this hook.
300 *
301 * @param $user
302 * The drupal user object that has requested the download
303 * @param $file_download
304 * The file download object as defined as a row from the uc_file_users table
305 * that grants the user the download
306 * @return
307 * TRUE or FALSE depending on whether the user is to be permitted download of
308 * the requested files. When a implementation returns FALSE it should set an
309 * error message in Drupal using drupal_set_message() to inform customers of
310 * what is going on.
311 */
312 function hook_download_authorize($user, $file_download) {
313 if (!$user->status) {
314 drupal_set_message(t("This account has been banned and can't download files anymore. "),'error');
315 return FALSE;
316 }
317 else {
318 return TRUE;
319 }
320 }
321
322 /**
323 * Perform actions on file products.
324 *
325 * The uc_file module comes with a file manager (found at Administer » Store
326 * administration » Products » View file downloads) that provides some basic
327 * functionality: deletion of multiple files and directories, and upload of single
328 * files (those looking to upload multiple files should just directly upload them
329 * to their file download directory then visit the file manager which automatically
330 * updates new files found in its directory). Developers that need to create more
331 * advanced actions with this file manager can do so by using this hook.
332 *
333 * @param $op
334 * The operation being taken by the hook, possible ops defined below.
335 * - 'info': Called before the uc_file module builds its list of possible file
336 * actions. This op is used to define new actions that will be placed in
337 * the file action select box.
338 * - 'insert': Called after uc_file discovers a new file in the file download
339 * directory.
340 * - 'form': When any defined file action is selected and submitted to the form
341 * this function is called to render the next form. Because this is called
342 * whenever a module-defined file action is selected, the variable
343 * $args['action'] can be used to define a new form or append to an existing
344 * form.
345 * - 'upload': After a file has been uploaded, via the file manager's built in
346 * file upload function, and moved to the file download directory this op
347 * can perform any remaining operations it needs to perform on the file
348 * before its placed into the uc_files table.
349 * - 'upload_validate': This op is called to validate the uploaded file that
350 * was uploaded via the file manager's built in file upload function. At
351 * this point, the file has been uploaded to PHP's temporary directory.
352 * Files passing this upload validate function will be moved into the file
353 * downloads directory.
354 * - 'validate': This op is called to validate the file action form.
355 * - 'submit': This op is called to submit the file action form.
356 * @param $args
357 * A keyed array of values that varies depending on the op being performed,
358 * possible values defined below.
359 * - 'info': None
360 * - 'insert':
361 * - 'file_object': The file object of the newly discovered file
362 * - 'form':
363 * - 'action': The file action being performed as defined by the key in the
364 * array sent by hook_file_action($op = 'info')
365 * - 'file_ids' - The file ids (as defined in the uc_files table) of the
366 * selected files to perform the action on
367 * - 'upload':
368 * - 'file_object': The file object of the file moved into file downloads
369 * directory
370 * - 'form_id': The form_id variable of the form_submit function
371 * - 'form_values': The form_values variable of the form_submit function
372 * - 'upload_validate':
373 * - 'file_object': The file object of the file that has been uploaded into
374 * PHP's temporary upload directory
375 * - 'form_id': The form_id variable of the form_validate function
376 * - 'form_values': The form_values variable of the form_validate function
377 * - 'validate':
378 * - 'form_id': The form_id variable of the form_validate function
379 * - 'form_values': The form_values variable of the form_validate function
380 * - 'submit':
381 * - 'form_id': The form_id variable of the form_submit function
382 * - 'form_values': The form_values variable of the form_submit function
383 * @return
384 * The return value of hook depends on the op being performed, possible return
385 * values defined below.
386 * - 'info': The associative array of possible actions to perform. The keys are
387 * unique strings that defines the actions to perform. The values are the
388 * text to be displayed in the file action select box.
389 * - 'insert': None
390 * - 'form': This op should return an array of drupal form elements as defined
391 * by the drupal form API.
392 * - 'upload': None
393 * - 'upload_validate': None
394 * - 'validate': None
395 * - 'submit': None
396 */
397 function hook_file_action($op, $args) {
398 switch ($op) {
399 case 'info':
400 return array('uc_image_watermark_add_mark' => 'Add Watermark');
401 case 'insert':
402 //automatically adds watermarks to any new files that are uploaded to the file download directory
403 _add_watermark($args['file_object']->filepath);
404 break;
405 case 'form':
406 if ($args['action'] == 'uc_image_watermark_add_mark') {
407 $form['watermark_text'] = array(
408 '#type' => 'textfield',
409 '#title' => t('Watermark Text'),
410 );
411 $form['submit_watermark'] = array(
412 '#type' => 'submit',
413 '#value' => t('Add Watermark'),
414 );
415 }
416 return $form;
417 case 'upload':
418 _add_watermark($args['file_object']->filepath);
419 break;
420 case 'upload_validate':
421 //Given a file path, function checks if file is valid JPEG
422 if(!_check_image($args['file_object']->filepath)) {
423 form_set_error('upload',t('Uploaded file is not a valid JPEG'));
424 }
425 break;
426 case 'validate':
427 if ($args['form_values']['action'] == 'uc_image_watermark_add_mark') {
428 if (empty($args['form_values']['watermark_text'])) {
429 form_set_error('watermar_text',t('Must fill in text'));
430 }
431 }
432 break;
433 case 'submit':
434 if ($args['form_values']['action'] == 'uc_image_watermark_add_mark') {
435 foreach ($args['form_values']['file_ids'] as $file_id) {
436 $filename = db_result(db_query("SELECT filename FROM {uc_files} WHERE fid = %d",$file_id));
437 //Function adds watermark to image
438 _add_watermark($filename);
439 }
440 }
441 break;
442 }
443 }
444
445 /**
446 * Make changes to a file before it is downloaded by the customer.
447 *
448 * Stores, either for customization, copy protection or other reasons, might want
449 * to send customized downloads to customers. This hook will allow this to happen.
450 * Before a file is opened to be transfered to a customer, this hook will be called
451 * to make any altercations to the file that will be used to transfer the download
452 * to the customer. This, in effect, will allow a developer to create a new,
453 * personalized, file that will get transfered to a customer.
454 *
455 * @param $file_user
456 * The file_user object (i.e. an object containing a row from the uc_file_users
457 * table) that corresponds with the user download being accessed.
458 * @param $ip
459 * The IP address from which the customer is downloading the file
460 * @param $fid
461 * The file id of the file being transfered
462 * @param $file
463 * The file path of the file to be transfered
464 * @return
465 * The path of the new file to transfer to customer.
466 */
467 function hook_file_transfer_alter($file_user, $ip, $fid, $file) {
468 $file_data = file_get_contents($file)." [insert personalized data]"; //for large files this might be too memory intensive
469 $new_file = tempnam(file_directory_temp(),'tmp');
470 file_put_contents($new_file,$file_data);
471 return $new_file;
472 }
473
474 /**
475 * Used to define line items that are attached to orders.
476 *
477 * A line item is a representation of charges, fees, and totals for an order.
478 * Default line items include the subtotal and total line items, the tax line
479 * item, and the shipping line item. There is also a generic line item that store
480 * admins can use to add extra fees and discounts to manually created orders.
481 * Module developers will use this hook to define new types of line items for
482 * their stores. An example use would be for a module that allows customers to
483 * use coupons and wants to represent an entered coupon as a line item.
484 *
485 * Once a line item has been defined in hook_line_item, Übercart will begin
486 * interacting with it in various parts of the code. One of the primary ways this
487 * is done is through the callback function you specify for the line item.
488 *
489 * @return
490 * Your hook should return an array of associative arrays. Each item in the
491 * array represents a single line item and should use the following keys:
492 * - "id"
493 * - type: string
494 * - value: The internal ID of the line item.
495 * - "title"
496 * - type: string
497 * - value: The title of the line item shown to the user in various interfaces.
498 * Use t().
499 * - "callback"
500 * - type: string
501 * - value: Name of the line item's callback function, called for various
502 * operations.
503 * - "weight"
504 * - type: integer
505 * - value: Display order of the line item in lists; "lighter" items are
506 * displayed first.
507 * - "stored"
508 * - type: boolean
509 * - value: Whether or not the line item will be stored in the database.
510 * Should be TRUE for any line item that is modifiable from the order
511 * edit screen.
512 * - "add_list"
513 * - type: boolean
514 * - value: Whether or not a line item should be included in the "Add a Line
515 * Item" select box on the order edit screen.
516 * - "calculated"
517 * - type: boolean
518 * - value: Whether or not the value of this line item should be added to the
519 * order total. (Ex: would be TRUE for a shipping charge line item but
520 * FALSE for the subtotal line item since the product prices are already
521 * taken into account.)
522 * - "display_only"
523 * - type: boolean
524 * - value: Whether or not this line item is simply a display of information
525 * but not calculated anywhere. (Ex: the total line item uses display to
526 * simply show the total of the order at the bottom of the list of line
527 * items.)
528 */
529 function hook_line_item() {
530 $items[] = array(
531 'id' => 'generic',
532 'title' => t('Empty Line'),
533 'weight' => 2,
534 'default' => FALSE,
535 'stored' => TRUE,
536 'add_list' => TRUE,
537 'calculated' => TRUE,
538 'callback' => 'uc_line_item_generic',
539 );
540
541 return $items;
542 }
543
544 /**
545 * Perform actions on orders.
546 *
547 * An order in Übercart represents a single transaction. Orders are created
548 * during the checkout process where they sit in the database with a status of In
549 * Checkout. When a customer completes checkout, the order's status gets updated
550 * to show that the sale has gone through. Once an order is created, and even
551 * during its creation, it may be acted on by any module to connect extra
552 * information to an order. Every time an action occurs to an order, hook_order()
553 * gets invoked to let your modules know what's happening and make stuff happen.
554 *
555 * @param $op
556 * The action being performed.
557 * @param &$arg1
558 * This is the order object or a reference to it as noted below.
559 * @param $arg2
560 * This is variable and is based on the value of $op:
561 * - new: Called when an order is created. $arg1 is a reference to the new
562 * order object, so modules may add to or modify the order at creation.
563 * - save: When an order object is being saved, the hook gets invoked with this
564 * op to let other modules do any necessary saving. $arg1 is a reference to
565 * the order object.
566 * - load: Called when an order is loaded after the order and product data has
567 * been loaded from the database. Passes $arg1 as the reference to the
568 * order object, so modules may add to or modify the order object when it's
569 * loaded.
570 * - submit: When a sale is being completed and the customer has clicked the
571 * Submit order button from the checkout screen, the hook is invoked with
572 * this op. This gives modules a chance to determine whether or not the
573 * order should be allowed. An example use of this is the credit module
574 * attempting to process payments when an order is submitted and returning
575 * a failure message if the payment failed.
576 *
577 * To prevent an order from passing through, you must return an array
578 * resembling the following one with the failure message:
579 * @code
580 * return array(array('pass' => FALSE, 'message' => t('We were unable to process your credit card.')));
581 * @endcode
582 * - can_update: Called before an order's status is changed to make sure the
583 * order can be updated. $arg1 is the order object with the old order
584 * status ID ($arg1->order_status), and $arg2 is simply the new order
585 * status ID. Return FALSE to stop the update for some reason.
586 * - update: Called when an order's status is changed. $arg1 is the order
587 * object with the old order status ID ($arg1->order_status), and $arg2 is
588 * the new order status ID.
589 * - can_delete: Called before an order is deleted to verify that the order may
590 * be deleted. Returning FALSE will prevent a delete from happening. (For
591 * example, the payment module returns FALSE by default when an order has
592 * already received payments.)
593 * - delete: Called when an order is deleted and before the rest of the order
594 * information is removed from the database. Passes $arg1 as the order
595 * object to let your module clean up it's tables.
596 * - total: Called when the total for an order is being calculated after the
597 * total of the products has been added. Passes $arg1 as the order object.
598 * Expects in return a value (positive or negative) by which to modify the
599 * order total.
600 */
601 function hook_order($op, &$arg1, $arg2) {
602 switch ($op) {
603 case 'save':
604 // Do something to save payment info!
605 break;
606 }
607 }
608
609 /**
610 * Add links to local tasks for orders on the admin's list of orders.
611 *
612 * @param $order
613 * An order object.
614 * @return
615 * An array of specialized link arrays. Each link has the following keys:
616 * - "name": The title of page being linked.
617 * - "url": The link path. Do not use url(), but do use the $order's order_id.
618 * - "icon": HTML of an image.
619 * - "title": Title attribute text (mouseover tool-tip).
620 */
621 function hook_order_actions($order) {
622 $actions = array();
623 $module_path = base_path() . drupal_get_path('module', 'uc_shipping');
624 if (user_access('fulfill orders')) {
625 $result = db_query("SELECT nid FROM {uc_order_products} WHERE order_id = %d AND data LIKE '%%s:9:\"shippable\";s:1:\"1\";%%'", $order->order_id);
626 if (db_num_rows($result)) {
627 $title = t('Package order !order_id products.', array('!order_id' => $order->order_id));
628 $actions[] = array(
629 'name' => t('Package'),
630 'url' => 'admin/store/orders/'. $order->order_id .'/packages',
631 'icon' => '<img src="'. $module_path .'/images/package.gif" alt="'. $title .'" />',
632 'title' => $title,
633 );
634 $result = db_query("SELECT package_id FROM {uc_packages} WHERE order_id = %d", $order->order_id);
635 if (db_num_rows($result)) {
636 $title = t('Ship order !order_id packages.', array('!order_id' => $order->order_id));
637 $actions[] = array(
638 'name' => t('Ship'),
639 'url' => 'admin/store/orders/'. $order->order_id .'/shipments',
640 'icon' => '<img src="'. $module_path .'/images/ship.gif" alt="'. $title .'" />',
641 'title' => $title,
642 );
643 }
644 }
645 }
646 return $actions;
647 }
648
649 /**
650 * Register callbacks for an order pane.
651 *
652 * This hook is used to add panes to the order viewing and administration screens.
653 * The default panes include areas to display and edit addresses, products,
654 * comments, etc. Developers should use this hook when they need to display or
655 * modify any custom data pertaining to an order. For example, a store that uses
656 * a custom checkout pane to find out a customer's desired delivery date would
657 * then create a corresponding order pane to show the data on the order screens.
658 *
659 * hook_order_pane() works by defining new order panes and providing a little bit
660 * of information about them. View the return value section below for information
661 * about what parts of an order pane are defined by the hook.
662 *
663 * The real meat of an order pane is its callback function (which is specified in
664 * the hook). The callback function handles what gets displayed on which screen
665 * and what data can be manipulated. That is all somewhat out of the scope of
666 * this API page, so you'll have to click here to read more about what a callback
667 * function should contain.
668 */
669 function hook_order_pane() {
670 $panes[] = array(
671 'id' => 'payment',
672 'callback' => 'uc_order_pane_payment',
673 'title' => t('Payment'),
674 'desc' => t('Specify and collect payment for an order.'),
675 'class' => 'pos-left',
676 'weight' => 4,
677 'show' => array('view', 'edit', 'customer'),
678 );
679 return $panes;
680 }
681
682 /**
683 * Register payment gateway callbacks.
684 *
685 * @see @link http://www.ubercart.org/docs/api/hook_payment_gateway @endlink
686 *
687 * @return
688 * Returns an array of payment gateways, which are arrays with the following keys:
689 * - "id"
690 * - type: string
691 * - value: The internal ID of the payment gateway, using a-z, 0-9, and - or
692 * _.
693 * - "title"
694 * - type: string
695 * - value: The name of the payment gateway displayed to the user. Use t().
696 * - "description"
697 * - type: string
698 * - value: A short description of the payment gateway.
699 * - "settings"
700 * - type: string
701 * - value: The name of a function that returns an array of settings form
702 * elements for the gateway.
703 */
704 function hook_payment_gateway() {
705 $gateways[] = array(
706 'id' => 'test_gateway',
707 'title' => t('Test Gateway'),
708 'description' => t('Process credit card payments through the Test Gateway.'),
709 'credit' => 'test_gateway_charge',
710 );
711 return $gateways;
712 }
713
714 /**
715 * Register callbacks for payment methods.
716 *
717 * Payment methods are different ways to collect payment. By default, Übercart
718 * comes with support for check, credit card, and generic payments. Payment
719 * methods show up at checkout or on the order administration screens, and they
720 * collect different sorts of information from the user that is used to process
721 * or track the payment.
722 *
723 * @return
724 * An array of payment methods.
725 */
726 function hook_payment_method() {
727 $methods[] = array(
728 'id' => 'check',
729 'name' => t('Check'),
730 'title' => t('Check or Money Order'),
731 'desc' => t('Pay by mailing a check or money order.'),
732 'callback' => 'uc_payment_method_check',
733 'weight' => 1,
734 'checkout' => TRUE,
735 );
736 return $methods;
737 }
738
739 /**
740 * Perform actions on product classes.
741 *
742 * @param $type
743 * The node type of the product class.
744 * @param $op
745 * The action being performed on the product class:
746 * - "insert": A new node type is created, or an existing node type is being
747 * converted into a product type.
748 * - "update": A product class has been updated.
749 * - "delete": A product class has been deleted. Modules that have attached
750 * additional information to the node type because it is a product type
751 * should delete this information.
752 */
753 function hook_product_class($type, $op) {
754 switch ($op) {
755 case 'delete':
756 db_query("DELETE FROM {uc_class_attributes} WHERE pcid = '%s'", $type);
757 db_query("DELETE FROM {uc_class_attribute_options} WHERE pcid = '%s'", $type);
758 break;
759 }
760 }
761
762 /**
763 * List node types which should be considered products.
764 *
765 * Trusts the duck philosophy of object identification: if it walks like a duck,
766 * quacks like a duck, and has feathers like a duck, it's probably a duck.
767 * Products are nodes with prices, SKUs, and everything else Übercart expects
768 * them to have.
769 *
770 * @return
771 * Array of node type ids.
772 */
773 function hook_product_types() {
774 return array('product_kit');
775 }
776
777 /**
778 * Handle additional data for shipments.
779 *
780 * @param $op
781 * The action being taken on the shipment. One of the following values:
782 * - "load": The shipment and its packages are loaded from the database.
783 * - "save": Changes to the shipment have been written.
784 * - "delete": The shipment has been deleted and the packages are available
785 * for reshipment.
786 * @param &$shipment
787 * The shipment object.
788 * @return
789 * Only given when $op is "load". An array of extra data to be added to the
790 * shipment object.
791 */
792 function hook_shipment($op, &$shipment) {
793 switch ($op) {
794 case 'save':
795 $google_order_number = uc_google_checkout_get_google_number($shipment->order_id);
796 if ($google_order_number && $shipment->is_new) {
797 $xml_data = '';
798 foreach ($shipment->packages as $package) {
799 if ($package->tracking_number) {
800 $tracking_number = $package->tracking_number;
801 }
802 else if ($shipment->tracking_number) {
803 $tracking_number = $shipment->tracking_number;
804 }
805 if ($tracking_number) {
806 foreach ($package->products as $product) {
807 $xml_data .= '<item-shipping-information>';
808 $xml_data .= '<item-id>';
809 $xml_data .= '<merchant-item-id>'. check_plain($product->nid .'|'. $product->model) .'</merchant-item-id>';
810 $xml_data .= '</item-id>';
811 $xml_data .= '<tracking-data-list>';
812 $xml_data .= '<tracking-data>';
813 $xml_data .= '<carrier>'. check_plain($shipment->carrier) .'</carrier>';
814 $xml_data .= '<tracking-number>'. check_plain($tracking_number) .'</tracking-number>';
815 $xml_data .= '</tracking-data>';
816 $xml_data .= '</tracking-data-list>';
817 $xml_data .= '</item-shipping-information>';
818 }
819 }
820 }
821 if ($xml_data) {
822 $request = '<?xml version="1.0" encoding="UTF-8"?>'. "\n";
823 $request .= '<ship-items xmlns="http://checkout.google.com/schema/2" google-order-number="'. $google_order_number .'">';
824 $request .= '<item-shipping-information-list>';
825 $request .= $xml_data;
826 $request .= '</item-shipping-information-list>';
827 $request .= '<send-email>true</send-email>';
828 $request .= '</ship-items>';
829 $response = uc_google_checkout_send_request('request', $request);
830 }
831 }
832 break;
833 case 'delete':
834 $google_order_number = uc_google_checkout_get_google_number($shipment->order_id);
835 if ($google_order_number) {
836 foreach ($shipment->packages as $package) {
837 foreach ($package->products as $product) {
838 $reset_ids[] = check_plain($product->nid .'|'. $product->model);
839 }
840 }
841 $request = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
842 $request .= '<reset-items-shipping-information xmlns="http://checkout.google.com/schema/2" google-order-number="'. $google_order_number .'">';
843 $request .= '<item-ids>';
844 foreach (array_unique($reset_ids) as $item_id) {
845 $request .= '<item-id>';
846 $request .= '<merchant-item-id>'. $item_id .'</merchant-item-id>';
847 $request .= '</item-id>';
848 }
849 $request .= '</item-ids>';
850 $request .= '<send-email>false</send-email>';
851 $request .= '</reset-items-shipping-information>';
852 }
853 $response = uc_google_checkout_send_request('request', $request);
854 break;
855 }
856 }
857
858 /**
859 * Define callbacks and service options for shipping methods.
860 *
861 * The shipping quote controller module, uc_quote, expects a very specific
862 * structured array of methods from the implementations of this hook.
863 *
864 * The weights and enabled flags for shipping methods and types are set at the
865 * Shipping Quote Settings page under Store Configuration. They keys of the
866 * variables are the ids of the shipping methods. The "quote" and "ship" arrays of
867 * the method are both optional.
868 *
869 * @return
870 * An array of shipping methods which have the following keys.
871 * - "type": The quote and shipping types are ids of the product shipping type
872 * that these methods apply to. type may also be 'order' which indicates
873 * that the quote applies to the entire order, regardless of the shipping
874 * types of its products. This is used by quote methods that are base on
875 * the location of the customer rather than their purchase.
876 * - "callback": The function that is called by uc_quote when a shipping quote
877 * is requested. Its arguments are the array of products and an array of
878 * order details (the shipping address). The return value is an array
879 * representing the rates quoted and errors returned (if any) for each
880 * option in the accessorials array.
881 * - "accessorials": This array represents the different options the customer
882 * may choose for their shipment. The callback function should generate a
883 * quote for each option in accessorials and return them via an array.
884 * drupal_to_js() is very useful for this.
885 * @code
886 * return array(
887 * '03' => array('rate' => 15.75, 'format' => uc_currency_format(15.75) 'option_label' => t('UPS Ground'),
888 * 'error' => 'Additional handling charge automatically applied.'),
889 * '14' => array('error' => 'Invalid package type.'),
890 * '59' => array('rate' => 26.03, 'format' => uc_currency_format(26.03), 'option_label' => t('UPS 2nd Day Air A.M.'))
891 * );
892 * @endcode
893 * - "pkg_types": The list of package types that the shipping method can handle.
894 * This should be an associative array that can be used as the #options of
895 * a select form element. It is recommended that a function be written to
896 * output this array so the method doesn't need to be found just for the
897 * package types.
898 */
899 function hook_shipping_method() {
900 $methods = array();
901
902 $enabled = variable_get('uc_quote_enabled', array('ups' => true));
903 $weight = variable_get('uc_quote_method_weight', array('ups' => 0));
904 $methods['ups'] = array(
905 'id' => 'ups',
906 'title' => t('UPS'),
907 'enabled' => $enabled['ups'],
908 'weight' => $weight['ups'],
909 'quote' => array(
910 'type' => 'small package',
911 'callback' => 'uc_ups_quote',
912 'accessorials' => array(
913 '03' => t('UPS Ground'),
914 '11' => t('UPS Standard'),
915 '01' => t('UPS Next Day Air'),
916 '13' => t('UPS Next Day Air Saver'),
917 '14' => t('UPS Next Day Early A.M.'),
918 '02' => t('UPS 2nd Day Air'),
919 '59' => t('UPS 2nd Day Air A.M.'),
920 '12' => t('UPS 3-Day Select'),
921 ),
922 ),
923 'ship' => array(
924 'type' => 'small package',
925 'callback' => 'uc_ups_fulfill_order',
926 'pkg_types' => array(
927 '01' => t('UPS Letter'),
928 '02' => t('Customer Supplied Package'),
929 '03' => t('Tube'),
930 '04' => t('PAK'),
931 '21' => t('UPS Express Box'),
932 '24' => t('UPS 25KG Box'),
933 '25' => t('UPS 10KG Box'),
934 '30' => t('Pallet'),
935 ),
936 ),
937 );
938
939 return $methods;
940 }
941
942 /**
943 * Define shipping types for shipping methods.
944 *
945 * This hook defines a shipping type that this module is designed to handle.
946 * These types are specified by a machine- and human-readable name called 'id',
947 * and 'title' respectively. Shipping types may be set for individual products,
948 * manufacturers, and for the entire store catalog. Shipping modules should be
949 * careful to use the same shipping type ids as other similar shipping modules
950 * (i.e., FedEx and UPS both operate on "small package" shipments). Modules that
951 * do not fulfill orders may not need to implement this hook.
952 *
953 * @return
954 * An array of shipping types keyed by a machine-readable name.
955 */
956 function hook_shipping_type() {
957 $weight = variable_get('uc_quote_type_weight', array('small_package' => 0));
958
959 $types = array();
960 $types['small_package'] = array(
961 'id' => 'small_package',
962 'title' => t('Small Packages'),
963 'weight' => $weight['small_package'],
964 );
965
966 return $types;
967 }
968
969 /**
970 * Add status messages to the "Store administration" page.
971 *
972 * This hook is used to add items to the store status table on the main store
973 * administration screen. Each item gets a row in the table that consists of a
974 * status icon, title, and description. These items should be used to give
975 * special instructions, notifications, or indicators for components of the cart
976 * enabled by the modules. At a glance, a store owner should be able to look here
977 * and see if a critical component of your module is not functioning properly.
978 *
979 * For example, if the catalog module is installed and it cannot find the catalog
980 * taxonomy vocabulary, it will show an error message here to alert the store
981 * administrator.
982 *
983 * @return
984 * An array of tore status items which are arrays with the following keys:
985 * - "status": "ok", "warning", or "error" depending on the message.
986 * - "title" The title of the status message or module that defines it.
987 * - "desc": The description; can be any message, including links to pages and
988 * forms that deal with the issue being reported.
989 */
990 function hook_store_status() {
991 if ($key = uc_credit_encryption_key()) {
992 $statuses[] = array(
993 'status' => 'ok',
994 'title' => t('Credit card encryption'),
995 'desc' => t('Credit card data in the database is currently being encrypted.'),
996 );
997 }
998 return $statuses;
999 }
1000
1001 /**
1002 * Convenience function to display large blocks of text in several places.
1003 *
1004 * There are many instances where Ubercart modules have configurable blocks of
1005 * text. These usually come with default messages, like e-mail templates for new
1006 * orders. Because of the way default values are normally set, you're then stuck
1007 * having to copy and paste a large chunk of text in at least two different
1008 * places in the module (when you're wanting to use the variable or to display
1009 * the settings form with the default value). To cut down code clutter, this hook
1010 * was introduced. It lets you put your messages in one place and use the
1011 * function uc_get_message() to retrieve the default value at any time (and from
1012 * any module).
1013 *
1014 * The function is very simple, expecting no arguments and returning a basic
1015 * associative array with keys being message IDs and their values being the
1016 * default message. When you call uc_get_message(), use the message ID you set
1017 * here to refer to the message you want.
1018 *
1019 * Note: When using t(), you must not pass it a concatenated string! So our
1020 * example has no line breaks in the message even though it is much wider than 80
1021 * characters. Using concatenation breaks translation.
1022 *
1023 * @return
1024 * An array of messages.
1025 */
1026 function hook_uc_message() {
1027 $messages['configurable_message_example'] = t('This block of text represents a configurable message such as a set of instructions or an e-mail template. Using hook_uc_message to handle the default values for these is so easy even your grandma can do it!');
1028
1029 return $messages;
1030 }
1031
1032 /**
1033 * Handle requests to update a cart item.
1034 *
1035 * @param $nid
1036 * Node id of the cart item.
1037 * @param $data
1038 * Array of extra information about the item.
1039 * @param $qty
1040 * The quantity of this item in the cart.
1041 * @param $cid
1042 * The cart id. Defaults to NULL, which indicates that the current user's cart
1043 * should be retrieved with uc_cart_get_id().
1044 */
1045 function hook_update_cart_item($nid, $data = array(), $qty, $cid = NULL) {
1046 if (!$nid) return NULL;
1047 $cid = !(is_null($cid) || empty($cid)) ? $cid : uc_cart_get_id();
1048 if ($qty < 1) {
1049 uc_cart_remove_item($nid, $cid, $data);
1050 }
1051 else {
1052 db_query("UPDATE {uc_cart_products} SET qty = %d, changed = %d WHERE nid = %d AND cart_id = '%s' AND data = '%s'", $qty, time(), $nid, $cid, serialize($data));
1053 cache_clear_all();
1054 }
1055
1056 // Rebuild the items hash
1057 uc_cart_get_contents(NULL, 'rebuild');
1058 if (!substr(request_uri(), 'cart', -4)) {
1059 drupal_set_message(t('Your item(s) have been updated.'));
1060 }
1061 }
1062
1063 /**
1064 * @} End of "addtogroup hooks".
1065 */

  ViewVC Help
Powered by ViewVC 1.1.2