/[drupal]/contributions/modules/uc_addresses/uc_addresses.module
ViewVC logotype

Contents of /contributions/modules/uc_addresses/uc_addresses.module

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


Revision 1.28 - (show annotations) (download) (as text)
Mon Apr 20 20:54:10 2009 UTC (7 months, 1 week ago) by freixas
Branch: MAIN
CVS Tags: HEAD
Changes since 1.27: +78 -64 lines
File MIME type: text/x-php
Placed admin functions in uc_addresses.admin.inc.
Added uc_addresses_js_util() to handle changes to country.
Fixed some variables that were used without being defined.
1 <?php
2 // $Id: uc_addresses.module,v 1.10 2008/06/25 03:21:58 freixas Exp $
3
4 /**
5 * @file
6 * Adds user profile address support to Ubercart.
7 *
8 * The uc_addresses module adds support for one or more addresses in
9 * the user's profile. When users register, they must provide an
10 * address. Users can then add more addresses and edit or delete
11 * existing addresses. One address must be designated as the default
12 * address and cannot be deleted (but it can be edited).
13 *
14 * The Ubercart order process is altered so that users select delivery
15 * and billing addresses from their collection of addresses rather
16 * than from previous orders. Any new addresses entered during the
17 * order process are automatically added to the user's list.
18 * <!--break-->
19 *
20 * @author Ben Thompson with inspiration from uc_order.module and uc_cart.module.
21 * @author Rich from Freestyle Systems (enhancements).
22 * @author Tony Freixas (maintainer) from Tiger Heron LLC (major revisions).
23 *
24 * @ingroup uc_addresses
25 */
26
27 /* TODO Implement the hook_theme registry. Combine all theme registry entries
28 into one hook_theme function in each corresponding module file.
29 */
30
31 module_load_include('inc', 'uc_addresses', 'uc_addresses_address_pane');
32
33 /**
34 * Give users the ability to view anyone's default address.
35 */
36 define('UC_ADDRESSES_ACCESS_VIEW_DEFAULT', 'view default addresses');
37
38 /**
39 * Give users the ability to view anyone's addresses.
40 * Anyone with this permission also has UC_ADDRESSES_ACCESS_VIEW_DEFAULT.
41 */
42 define('UC_ADDRESSES_ACCESS_VIEW_ALL', 'view all addresses');
43
44 /**
45 * Give users the ability to add or edit anyone's addresses.
46 * Anyone with this permission also has
47 * UC_ADDRESSES_ACCESS_VIEW_DEFAULT and UC_ADDRESSES_ACCESS_VIEW_ALL.
48 */
49 define('UC_ADDRESSES_ACCESS_ADD_EDIT', 'add/edit addresses');
50
51 /*******************************************************************************
52 * Hook Functions
53 ******************************************************************************/
54
55 /**
56 * Implementation of hook_init()
57 */
58 function uc_addresses_init() {
59 drupal_add_css(drupal_get_path('module', 'uc_order') .'/uc_order.css');
60 }
61
62 /**
63 * Given a wildcard of %uc_addresses_address in path, replace it with
64 * the corresponding address object.
65 *
66 * @param $aid The value matched by %uc_addresses_address.
67 * @param $uid The value of the user ID in the same path.
68 * @return FALSE if the value is a valid address, else the address object.
69 */
70 function uc_addresses_address_load($aid, $uid) {
71 if (!isset($aid)) return FALSE;
72 return _uc_addresses_db_get_address($uid, $aid);
73 }
74
75 /**
76 * Implementation of hook_menu().
77 *
78 * @return A array of menu items.
79 */
80 function uc_addresses_menu() {
81 global $user;
82 $items = array();
83
84 $items['admin/store/settings/addresses'] = array(
85 'title' => 'Address settings',
86 'description' => 'Configure the address settings.',
87 'page callback' => 'uc_addresses_settings_overview',
88 'access arguments' => array('administer store'),
89 'type' => MENU_NORMAL_ITEM,
90 'file' => 'uc_addresses.admin.inc',
91 );
92 $items['admin/store/settings/addresses/overview'] = array(
93 'title' => 'Overview',
94 'access arguments' => array('administer store'),
95 'description' => 'View the address settings.',
96 'type' => MENU_DEFAULT_LOCAL_TASK,
97 'weight' => -10,
98 );
99 $items['admin/store/settings/addresses/edit'] = array(
100 'title' => 'Edit',
101 'page callback' => 'drupal_get_form',
102 'page arguments' => array('uc_addresses_settings_form'),
103 'access arguments' => array('administer store'),
104 'description' => 'Edit the address settings.',
105 'type' => MENU_LOCAL_TASK,
106 'weight' => -5,
107 'file' => 'uc_addresses.admin.inc',
108 );
109
110 $items['user/%user_uid_optional/addresses'] = array(
111 'title' => 'Addresses',
112 'description' => 'Manage your addresses',
113 'page callback' => 'uc_addresses_list_addresses',
114 'page arguments' => array(1, NULL),
115 'access callback' => 'uc_addresses_can_view_addresses',
116 'access arguments' => array(1),
117 'type' => MENU_LOCAL_TASK,
118 );
119
120 $items['user/%user_uid_optional/addresses/list'] = array(
121 'title' => 'Address list',
122 'description' => 'Manage your addresses',
123 'access callback' => 'uc_addresses_can_view_addresses',
124 'access arguments' => array(1),
125 'type' => MENU_DEFAULT_LOCAL_TASK,
126 'weight' => 0,
127 );
128 $items['user/%user_uid_optional/addresses/add'] = array(
129 'title' => 'Add address',
130 'description' => 'Add a new address.',
131 'page callback' => 'drupal_get_form',
132 'page arguments' => array('uc_addresses_get_address_form', 1, NULL, 'add'),
133 'access callback' => 'uc_addresses_can_add_edit_address',
134 'access arguments' => array(1),
135 'type' => MENU_LOCAL_TASK,
136 'weight' => 3,
137 );
138
139 $items['user/%user_uid_optional/addresses/%uc_addresses_address'] = array(
140 'title' => 'View Address',
141 'description' => 'View one saved address',
142 'load arguments' => array(1),
143 'page callback' => 'uc_addresses_list_addresses',
144 'page arguments' => array(1, arg(3)),
145 'access callback' => 'uc_addresses_can_view_addresses',
146 'access arguments' => array(1),
147 'type' => MENU_CALLBACK,
148 );
149 $items['user/%user_uid_optional/addresses/%uc_addresses_address/edit'] = array(
150 'title' => 'Edit address',
151 'load arguments' => array(1),
152 'page callback' => 'drupal_get_form',
153 'page arguments' => array('uc_addresses_get_address_form', 1, 3, 'edit'),
154 'access callback' => 'uc_addresses_can_add_edit_address',
155 'access arguments' => array(1),
156 'type' => MENU_CALLBACK,
157 );
158 $items['user/%user_uid_optional/addresses/%uc_addresses_address/delete'] = array(
159 'title' => 'Delete address',
160 'load arguments' => array(1),
161 'page callback' => 'uc_addresses_delete_address_confirm',
162 'page arguments' => array(1, 3),
163 'access callback' => 'uc_addresses_can_add_edit_address',
164 'access arguments' => array(1),
165 'type' => MENU_CALLBACK,
166 );
167 $items['uc_addresses_js_util'] = array(
168 'page callback' => 'uc_addresses_js_util',
169 'access arguments' => array('access content'),
170 'type' => MENU_CALLBACK,
171 );
172
173 return $items;
174 }
175
176 /**
177 * Implementation of hook_theme.
178 */
179 function uc_addresses_theme() {
180 return array(
181 'uc_addresses_list_address' => array(
182 'arguments' => array('address' => NULL, 'panes' => array()),
183 ),
184 'uc_addresses_get_address_form' => array(
185 'arguments' => array('form' => NULL),
186 ),
187 'uc_addresses_address_delete_confirm' => array(
188 'arguments' => array('help' => '', 'panes' => array(), 'form' => NULL),
189 ),
190 'uc_addresses_pane' => array(
191 'arguments' => array('form' => NULL),
192 'file' => 'uc_addresses_address_pane.inc',
193 ),
194 );
195 }
196
197 /**
198 * Implementation of hook_perm().
199 *
200 * @return array An array of permission names.
201 */
202 function uc_addresses_perm() {
203 return array(UC_ADDRESSES_ACCESS_VIEW_DEFAULT,
204 UC_ADDRESSES_ACCESS_VIEW_ALL,
205 UC_ADDRESSES_ACCESS_ADD_EDIT);
206 }
207
208 function uc_addresses_can_view_addresses($address_user) {
209 global $user;
210
211 $access =
212 user_access(UC_ADDRESSES_ACCESS_VIEW_DEFAULT) ||
213 user_access(UC_ADDRESSES_ACCESS_VIEW_ALL) ||
214 user_access(UC_ADDRESSES_ACCESS_ADD_EDIT) ||
215 $user->uid == $address_user->uid;
216
217 return $access;
218 }
219
220 function uc_addresses_can_add_edit_address($address_user) {
221 global $user;
222
223 $access =
224 user_access(UC_ADDRESSES_ACCESS_ADD_EDIT) ||
225 $user->uid == $address_user->uid;
226
227 return $access;
228 }
229
230 /**
231 * Implementation of hook_user().
232 *
233 * @param $op An integer representing the action being performed.
234 * @param $edit An array of form values submitted by the user.
235 * @param $account The user on which the operation is being performed.
236 * @param $category The active category of user information being edited.
237 */
238 function uc_addresses_user($op, &$edit, &$account, $category = NULL) {
239 global $user;
240 switch ($op) {
241 case 'register':
242 // For registration, we may want the user to enter his default
243 // address
244
245 if (variable_get('uc_addresses_require_address', TRUE)) {
246 $form = uc_addresses_pane_address('new', NULL, $edit);
247 $form = array($form['contents']); // Modify to what we need
248 $form[0]['#title'] = t('Address'); // Rename the fieldset
249 return $form;
250 }
251
252 case 'insert':
253 // We're about to add the user to the database, so get the address
254 // info and add it to the address table
255
256 $address = (object)$edit;
257 $address->is_default = 0;
258 _uc_addresses_db_add_address($address);
259 return;
260
261 case 'delete':
262 // We're deleting the user, so delete all his/her addresses as
263 // well
264
265 db_query("DELETE FROM {uc_addresses} WHERE uid = %d", $account->uid);
266 db_query("DELETE FROM {uc_addresses_defaults} WHERE uid = %d", $account->uid);
267 return;
268 }
269 }
270
271 /**
272 * Implementation of hook_form_alter().
273 *
274 * Here we're going to override the saved address options on the
275 * checkout form.
276 *
277 * @param $form The form array.
278 * @param $form_state A keyed array containing the current state of
279 * the form.
280 */
281 function uc_addresses_form_uc_cart_checkout_form_alter(&$form, &$form_state) {
282 global $user;
283
284 // This is a good place to clear any addresses we might have
285 // leftover from a previous checkout
286
287 if (isset($_SESSION['uc_addresses_saved_addresses'])) {
288 $_SESSION['uc_addresses_saved_addresses'] = null;
289 unset($_SESSION['uc_addresses_saved_addresses']);
290 }
291
292 // Create the list of addresses the user can select from
293 // Each address is just line a full address, but on one line
294
295 $options = NULL;
296 if ($addresses = _uc_addresses_db_get_address($user->uid)) {
297 $options = array('0' => t('Select one...'));
298 foreach ($addresses as $address) {
299 $address = (array)$address;
300
301 if ($address['address_name']) {
302 $options[drupal_to_js($address)] = $address['address_name'];
303 }
304
305 else {
306 // Not happy about this--if uc_address_format() ever changes
307 // it's output, we're hosed
308
309 $options[drupal_to_js($address)] =
310 preg_replace('/<.*?>/', ', ',
311 uc_address_format(
312 $address['first_name'],
313 $address['last_name'],
314 $address['company'],
315 $address['street1'],
316 $address['street2'],
317 $address['city'],
318 $address['zone'],
319 $address['postal_code'],
320 $address['country']));
321 }
322 }
323 }
324
325 $address_book_icon =
326 l(uc_store_get_icon('file:address_book', FALSE, 'address-book-icon'),
327 'user/'. $user->uid . '/addresses', array('html' => TRUE));
328
329 // If we have some addresses saved (almost always true), revise
330 // the delivery/billing address selection
331
332 if ($options) {
333 drupal_add_js(drupal_get_path('module', 'uc_addresses') .'/uc_addresses.js');
334
335 // Might not have any shippable products so make sure the
336 // delivery address exists before mucking with it
337
338 if ($form['panes']['delivery'] &&
339 ((uc_cart_is_shippable() || !variable_get('uc_cart_delivery_not_shippable', TRUE)))) {
340 if (variable_get('uc_pane_delivery_enabled', TRUE)) {
341 $form['panes']['delivery']['#description'] =
342 (variable_get('uc_addresses_default_delivery_address', TRUE) ?
343 t('Edit the address below or select an address from the list. ') :
344 t('Enter an address below or select an address from the list. ')) .
345 t('Click !here to manage your saved addresses.',
346 array('!here' => l(t('here'), 'user/'. $user->uid . '/addresses')));
347
348 $form['panes']['delivery']['delivery_address_select'] = array(
349 '#type' => 'select',
350 '#title' => t('Saved addresses'),
351 '#options' => $options,
352 '#attributes' => array('onchange' => 'apply_address(\'delivery\', this.value);'),
353 '#suffix' => $address_book_icon,
354 '#weight' => -10,
355 );
356 }
357 }
358
359 if (variable_get('uc_pane_billing_enabled', TRUE)) {
360 $form['panes']['billing']['#description'] =
361 (variable_get('uc_addresses_default_billing_address', TRUE) ?
362 t('Edit the address below or select an address from the list. ') :
363 t('Enter an address below or select an address from the list. ')) .
364 t('Click !here to manage your saved addresses.',
365 array('!here' => l(t('here'), 'user/'. $user->uid . '/addresses')));
366
367 $form['panes']['billing']['billing_address_select'] = array(
368 '#type' => 'select',
369 '#title' => t('Saved addresses'),
370 '#options' => $options,
371 '#attributes' => array('onchange' => 'apply_address(\'billing\', this.value);'),
372 '#suffix' => $address_book_icon,
373 '#weight' => -10,
374 );
375 }
376
377 // Copy the default address to the delivery address fields if
378 // the option is enabled and if the fields are empty
379
380 if ($form['panes']['delivery'] &&
381 ((uc_cart_is_shippable() || !variable_get('uc_cart_delivery_not_shippable', TRUE)))) {
382 if (variable_get('uc_addresses_default_delivery_address', TRUE) &&
383 variable_get('uc_pane_delivery_enabled', TRUE) &&
384 _uc_addresses_address_fields_empty($form['panes']['delivery'], 'delivery')) {
385 foreach ($addresses as $address) {
386 if ($address->is_default) {
387 if (uc_address_field_enabled('first_name')) {
388 $form['panes']['delivery']['delivery_first_name']['#default_value'] = $address->first_name;
389 }
390 if (uc_address_field_enabled('last_name')) {
391 $form['panes']['delivery']['delivery_last_name']['#default_value'] = $address->last_name;
392 }
393 if (uc_address_field_enabled('phone')) {
394 $form['panes']['delivery']['delivery_phone']['#default_value'] = $address->phone;
395 }
396 if (uc_address_field_enabled('company')) {
397 $form['panes']['delivery']['delivery_company']['#default_value'] = $address->company;
398 }
399 if (uc_address_field_enabled('street1')) {
400 $form['panes']['delivery']['delivery_street1']['#default_value'] = $address->street1;
401 }
402 if (uc_address_field_enabled('street2')) {
403 $form['panes']['delivery']['delivery_street2']['#default_value'] = $address->street2;
404 }
405 if (uc_address_field_enabled('city')) {
406 $form['panes']['delivery']['delivery_city']['#default_value'] = $address->city;
407 }
408 if (uc_address_field_enabled('country')) {
409 $form['panes']['delivery']['delivery_country']['#default_value'] = $address->country;
410 }
411 if (uc_address_field_enabled('zone')) {
412 $form['panes']['delivery']['delivery_zone'] =
413 uc_zone_select(
414 $form['panes']['delivery']['delivery_zone']['#title'],
415 $address->zone,
416 $form['panes']['delivery']['delivery_zone']['#description'],
417 $address->country,
418 'name',
419 $form['panes']['delivery']['delivery_zone']['#required']);
420 }
421 if (uc_address_field_enabled('postal_code')) {
422 $form['panes']['delivery']['delivery_postal_code']['#default_value'] = $address->postal_code;
423 }
424 }
425 }
426 }
427 }
428
429 // Copy the default address to the billing address fields if the
430 // option is enabled and if the fields are empty
431
432 if (variable_get('uc_addresses_default_billing_address', TRUE) &&
433 variable_get('uc_pane_billing_enabled', TRUE) &&
434 _uc_addresses_address_fields_empty($form['panes']['billing'], 'billing')) {
435 foreach ($addresses as $address) {
436 if ($address->is_default) {
437 if (uc_address_field_enabled('first_name')) {
438 $form['panes']['billing']['billing_first_name']['#default_value'] = $address->first_name;
439 }
440 if (uc_address_field_enabled('last_name')) {
441 $form['panes']['billing']['billing_last_name']['#default_value'] = $address->last_name;
442 }
443 if (uc_address_field_enabled('phone')) {
444 $form['panes']['billing']['billing_phone']['#default_value'] = $address->phone;
445 }
446 if (uc_address_field_enabled('company')) {
447 $form['panes']['billing']['billing_company']['#default_value'] = $address->company;
448 }
449 if (uc_address_field_enabled('street1')) {
450 $form['panes']['billing']['billing_street1']['#default_value'] = $address->street1;
451 }
452 if (uc_address_field_enabled('street2')) {
453 $form['panes']['billing']['billing_street2']['#default_value'] = $address->street2;
454 }
455 if (uc_address_field_enabled('city')) {
456 $form['panes']['billing']['billing_city']['#default_value'] = $address->city;
457 }
458 if (uc_address_field_enabled('country')) {
459 $form['panes']['billing']['billing_country']['#default_value'] = $address->country;
460 }
461 if (uc_address_field_enabled('zone')) {
462 $form['panes']['billing']['billing_zone'] =
463 uc_zone_select(
464 $form['panes']['billing']['billing_zone']['#title'],
465 $address->zone,
466 $form['panes']['billing']['billing_zone']['#description'],
467 $address->country,
468 'name',
469 $form['panes']['billing']['billing_zone']['#required']);
470 }
471 if (uc_address_field_enabled('postal_code')) {
472 $form['panes']['billing']['billing_postal_code']['#default_value'] = $address->postal_code;
473 }
474 }
475 }
476 }
477 }
478
479 // If we have no addresses, remove the selection field. This
480 // occurs only when this module is added to a system that already
481 // has users
482
483 else {
484 unset($form['panes']['delivery']['delivery_address_select']);
485 unset($form['panes']['billing']['billing_address_select']);
486 }
487
488 // Add the "Save address" checkbox
489 // TODO: (Tony) I can add these, but don't know how to find out if
490 // the checkbox was checked. For now, all order addresses are
491 // automatically saved.
492
493 // $form['panes']['billing']['billing_address_save_address'] = array(
494 // '#title' => t('Save this address'),
495 // '#type' => 'checkbox',
496 // '#default_value' => 1,
497 // '#weight' => 10
498 // );
499 // $form['panes']['delivery']['delivery_address_save_address'] = array(
500 // '#title' => t('Save this address'),
501 // '#type' => 'checkbox',
502 // '#default_value' => 1,
503 // '#weight' => 10
504 // );
505
506 }
507
508 function _uc_addresses_address_fields_empty($fields, $type)
509 {
510 if (uc_address_field_enabled('first_name') &&
511 $fields[$type . '_first_name']['#default_value']) return FALSE;
512 else if (uc_address_field_enabled('last_name') &&
513 $fields[$type . '_last_name']['#default_value']) return FALSE;
514 else if (uc_address_field_enabled('phone') &&
515 $fields[$type . '_phone']['#default_value']) return FALSE;
516 else if (uc_address_field_enabled('company') &&
517 $fields[$type . '_company']['#default_value']) return FALSE;
518 else if (uc_address_field_enabled('street1') &&
519 $fields[$type . '_street1']['#default_value']) return FALSE;
520 else if (uc_address_field_enabled('street2') &&
521 $fields[$type . '_street2']['#default_value']) return FALSE;
522 else if (uc_address_field_enabled('city') &&
523 $fields[$type . '_city']['#default_value']) return FALSE;
524 else if (uc_address_field_enabled('postal_code') &&
525 $fields[$type . '_postal_code']['#default_value']) return FALSE;
526 return TRUE;
527 }
528
529 /*******************************************************************************
530 * Hook Functions (Ubercart)
531 ******************************************************************************/
532
533 /**
534 * Implementation of hook_address_pane().
535 *
536 * @return array
537 */
538 function uc_addresses_address_pane() {
539 $panes[] = array(
540 'id' => 'address',
541 'callback' => 'uc_addresses_pane_address',
542 'title' => t('Address'),
543 'desc' => t("Manage the user's addresses and contact information."),
544 'class' => 'pos-left',
545 'weight' => 1,
546 'show' => array('view', 'add', 'edit'),
547 );
548
549 return $panes;
550 }
551
552 /**
553 * Use hook_order to add an address or two to the user's address list.
554 * For the moment, we save all addresses. I'd like to add an option to
555 * let the user select which addresses get saved.
556 *
557 * @param $op The operation being performed.
558 * @param $arg1 A reference to the order object.
559 * @param $arg2 Not used.
560 */
561 function uc_addresses_order($op, &$arg1, $arg2) {
562 global $user;
563 $order = $arg1;
564
565 if ($op == 'submit' && $order->order_status == 'in_checkout') {
566 $address = new stdClass();
567
568 // Add the billing address first. If the user has no addresses,
569 // this is the one that will become the default address
570
571 if (variable_get('uc_pane_billing_enabled', TRUE)) {
572 $address->address_name = '';
573 $address->uid = $order->uid;
574 $address->first_name = $order->billing_first_name;
575 $address->last_name = $order->billing_last_name;
576 $address->company = $order->billing_company;
577 $address->street1 = $order->billing_street1;
578 $address->street2 = $order->billing_street2;
579 $address->city = $order->billing_city;
580 $address->zone = $order->billing_zone;
581 $address->postal_code = $order->billing_postal_code;
582 $address->country = $order->billing_country;
583 $address->phone = $order->billing_phone;
584 $address->is_default = 0;
585 _uc_addresses_db_add_address($address, TRUE);
586 }
587
588 if (variable_get('uc_pane_delivery_enabled', TRUE) &&
589 (uc_cart_is_shippable() || !variable_get('uc_cart_delivery_not_shippable', TRUE))) {
590 $address->address_name = '';
591 $address->uid = $order->uid;
592 $address->first_name = $order->delivery_first_name;
593 $address->last_name = $order->delivery_last_name;
594 $address->company = $order->delivery_company;
595 $address->street1 = $order->delivery_street1;
596 $address->street2 = $order->delivery_street2;
597 $address->city = $order->delivery_city;
598 $address->zone = $order->delivery_zone;
599 $address->postal_code = $order->delivery_postal_code;
600 $address->country = $order->delivery_country;
601 $address->phone = $order->delivery_phone;
602 $address->is_default = 0;
603 _uc_addresses_db_add_address($address, TRUE);
604 }
605 }
606
607 // We have a user that is logged out, but the order system located
608 // an existing user that matches the email for the order
609
610 else if ($user->uid == 0 && $order->uid != 0 &&
611 _uc_addresses_db_have_saved_addresses()) {
612 $address = new stdClass();
613 $address->uid = $order->uid;
614 _uc_addresses_db_add_address($address, TRUE);
615 }
616 }
617
618 /*******************************************************************************
619 * Callback Functions, Forms, and Tables
620 ******************************************************************************/
621
622 /**
623 * Generate a list of one or all addresses defined by one user and
624 * then theme the list for display.
625 *
626 * If the current user can edit the addresses, then provide an edit
627 * link for each address.
628 *
629 * @param $address_user The user whose address list we want to display.
630 * @param $address The address to display or null to display all.
631 * @return The themed list (as a string).
632 */
633 function uc_addresses_list_addresses($address_user, $address = NULL) {
634 global $user;
635
636 $uid = $address_user->uid;
637
638 // Save this for later use
639
640 $saved_address = $address;
641
642 // Determine if the user can view all addresses or just the default address
643
644 $can_view_all_addresses =
645 $user->uid == $uid ||
646 user_access(UC_ADDRESSES_ACCESS_VIEW_ALL) ||
647 user_access(UC_ADDRESSES_ACCESS_ADD_EDIT);
648
649 // Flag to determine error message
650
651 $allowed_to_view_address = true;
652
653 // If they can view all addresses, fetch the addresses
654
655 if ($can_view_all_addresses) {
656 if ($address) {
657 $addresses = $address;
658 }
659 else {
660 $addresses = _uc_addresses_db_get_address($uid, NULL);
661 }
662 }
663
664 // Otherwise, they can view only the default address
665
666 else {
667 if ($address) {
668 if ($address->is_default === false) {
669 $addresses = FALSE;
670 $allowed_to_view_address = FALSE;
671 }
672 }
673 else {
674 $aid = _uc_addresses_get_default_address_id($uid);
675 if ($aid === NULL) $aid = 0; // NULL would mean read all addresses
676
677 $addresses = _uc_addresses_db_get_address($uid, $aid);
678 if (is_object($addresses) && $addresses->is_default === false) {
679 $addresses = FALSE;
680 $allowed_to_view_address = FALSE;
681 }
682 }
683 }
684
685 $output = '';
686
687 // We have multiple addresses
688
689 if (is_array($addresses)) {
690 foreach ($addresses as $address) {
691 $output .= _uc_addresses_list_one_address($address);
692 }
693 }
694
695 // We have one address
696
697 elseif (is_object($addresses)) {
698 $output .= _uc_addresses_list_one_address($addresses);
699 }
700
701 // We don't have any addresses. The message we report depends on the
702 // user and what they asked for
703
704 else {
705
706 // If they asked for all addresses and got nothing, it's because
707 // there is nothing
708
709 if ($saved_address === NULL) {
710 $output .= t('No addresses have been saved.<br />');
711 }
712
713 // If they asked for a specific address, it could be because it
714 // doesn't exist or because they are only permitted to view the
715 // default address and the one they picked is not the default
716
717 elseif ($allowed_to_view_address) {
718 $output .= t('This address does not exist.<br />');
719 }
720
721 else {
722 $output .= t('You are not allowed to view this address.<br />');
723 }
724 }
725
726 // Decide whether to include a link for adding a new address based
727 // on whether the current user can edit the addresses
728
729 if (user_access(UC_ADDRESSES_ACCESS_ADD_EDIT) || $user->uid == $uid) {
730 $link = l(t('Add a new address'), 'user/'. $uid .'/addresses/add');
731 $output .= $link;
732 }
733
734 return $output;
735 }
736
737 /**
738 * List one address.
739 *
740 * @param $address The address object to list.
741 * @return The HTML string for the address.
742 */
743 function _uc_addresses_list_one_address($address) {
744
745 $panes = _address_pane_list();
746 foreach ($panes as $pane) {
747 if (variable_get('uc_addresses_pane_'. $pane['id'] .'_enabled', TRUE)) {
748 $func = $pane['callback'];
749 if (function_exists($func)) {
750 $return = $func('view', $address, NULL);
751 if (!is_NULL($return)) {
752 $data[$pane['title']] = $return;
753 }
754 }
755 }
756 }
757 $output = '<div class="list_address">';
758 $output .= theme('uc_addresses_list_address', $address, $data);
759 $output .= '</div>';
760 return $output;
761 }
762
763 /**
764 * Theme the address list view.
765 *
766 * @param $address The address object we are theming.
767 * @param $panes An associative array for each address pane.
768 * The key is the pane's title and the value is either the data
769 * returned for that pane or an array of returned data.
770 * @return The themed address.
771 * @ingroup themeable
772 */
773 function theme_uc_addresses_list_address($address, $panes) {
774 global $user;
775
776 $uid = $address->uid;
777 $aid = $address->aid;
778
779 drupal_add_css(drupal_get_path('module', 'uc_addresses') .'/uc_addresses.css');
780
781 $output = '';
782 if ($address->is_default) {
783 $output = '<table class="address-preview-table addresses-default-address">';
784 }
785 else {
786 $output = '<table class="address-preview-table">';
787 }
788
789 foreach ($panes as $title => $data) {
790
791 // We add an edit link only if the user is allowed to edit this address
792
793 if (user_access(UC_ADDRESSES_ACCESS_ADD_EDIT) || $user->uid == $uid) {
794 $output .= '<tr class="pane-title-row"><td colspan="2">'
795 . l(t('Edit this address'), 'user/'. $uid .'/addresses/' . $aid . '/edit')
796 . ($address->is_default ? '' :
797 ' | '
798 . l(t('Delete this address'), 'user/'. $uid .'/addresses/' . $aid . '/delete'))
799 .'</td></tr>';
800 }
801
802 if ($address->is_default) {
803 $output .= '<tr><td colspan="2" class="addresses-default-address-label"> '
804 . t('Default address') . '</td></tr>';
805 }
806
807 if ($address->address_name) {
808 $output .=
809 '<tr class="pane-data-row"><td class="title-col" '
810 .'>'.t('Name') .':</td><td class="data-col">'
811 . $address->address_name .'</td></tr>';
812 }
813
814 if (is_array($data)) {
815 foreach ($data as $row) {
816 if (is_array($row)) {
817 if (isset($row['border'])) {
818 $border = ' class="row-border-'. $row['border'] .'"';
819 }
820 else {
821 $border = '';
822 }
823 $output .= '<tr class="pane-data-row"'. $border .'><td class="title-col" '
824 .'>'. $row['title'] .':</td><td class="data-col">'
825 . $row['data'] .'</td></tr>';
826 }
827 else {
828 $output .= '<tr class="pane-data-row"><td colspan="2">'. $row .'</td></tr>';
829 }
830 }
831 }
832 else {
833 $output .= '<tr class="pane-data-row"><td colspan="2">'. $data .'</td></tr>';
834 }
835 }
836 $output .= '</table><br />';
837
838 return $output;
839 }
840
841 /**
842 * Create a form used to add a new address or edit an existing address.
843 *
844 * @param $form_state The form state.
845 * @param $address_user The user who "owns" this address.
846 * @param $address The address to edit (NULL for new addresses)
847 * @param $view The URL path for which form to display. 'add' or 'edit'.
848 * @return An address form
849 * @ingroup forms
850 */
851 function uc_addresses_get_address_form(&$form_state, $address_user, $address, $view) {
852
853 $uid = $address_user->uid;
854 $aid = $address ? $address->aid : 0;
855 $form_state['storage']['user'] = $address_user;
856 $form_state['storage']['address'] = $address;
857 $form_state['storage']['view'] = $view;
858
859 // Get the panes to display
860
861 $form['panes'] = array('#tree' => TRUE);
862 $panes = _address_pane_list($view);
863 foreach ($panes as $pane) {
864 if (in_array($view, $pane['show']) &&
865 variable_get('uc_addresses_pane_'. $pane['id'] .'_show_'. $view, TRUE)) {
866 $return = $pane['callback']($view, $address, NULL);
867
868 // Add the pane if any display data is returned from the
869 // callback
870
871 if (is_array($return) && (!empty($return['description']) || !empty($return['contents']))) {
872
873 // Create the fieldset for the pane
874
875 $form['panes'][$pane['id']] = array(
876 '#type' => 'fieldset',
877 '#title' => $pane['title'],
878 '#description' => !empty($return['description']) ? $return['description'] : NULL,
879 '#collapsible' => !empty($pane['collapsible']) ? $pane['collapsible'] : FALSE,
880 '#collapsed' => FALSE,
881 '#attributes' => array('id' => $pane['id'] .'-pane'),
882 '#theme' => $return['theme'],
883 );
884
885 // Add the contents of the fieldset if any were returned
886
887 if (!empty($return['contents'])) {
888 $form['panes'][$pane['id']] = array_merge($form['panes'][$pane['id']], $return['contents']);
889 }
890 }
891 }
892 }
893
894 // Edit an existing address
895
896 if ($view == 'edit') {
897 $form['submit'] =
898 array('#type' => 'submit',
899 '#value' => variable_get('uc_addresses_update_button', t('Update address')));
900 $form['delete'] =
901 array('#type' => 'submit',
902 '#value' => variable_get('uc_addresses_delete_button', t('Delete address')),
903 '#suffix' => l(t('Cancel'), 'user/'. $uid .'/addresses/'),
904 '#disabled' => $address->is_default);
905 }
906
907 // Add a new address
908
909 else {
910 $form['submit'] =
911 array('#type' => 'submit',
912 '#value' => variable_get('uc_addresses_update_button', t('Add address')),
913 '#suffix' => l(t('Cancel'), 'user/'. $uid .'/addresses/'));
914 }
915
916 return $form;
917 }
918
919 /**
920 * Theme the add or edit address form.
921 *
922 * @param $form The form array to theme.
923 * @return The themed form (as a string).
924 * @ingroup themeable
925 */
926 function theme_uc_addresses_get_address_form($form) {
927 drupal_add_css(drupal_get_path('module', 'uc_addresses') .'/uc_addresses.css');
928
929 $output = '<p>';
930
931 foreach (element_children($form['panes']) as $pane_id) {
932
933 // TODO: (Tony) Not sure what's going on here.
934
935 if (function_exists(($func = _address_pane_data($pane_id, 'callback')))) {
936 $result = $func('theme', $form['panes'][$pane_id], NULL);
937 if (!empty($result)) {
938 $output .= $result;
939 $form['panes'][$pane_id] = array();
940 }
941 else {
942 $output .= drupal_render($form['panes'][$pane_id]);
943 }
944 }
945 else {
946 $output .= drupal_render($form['panes'][$pane_id]);
947 }
948 }
949
950 $output .= '<div id="checkout-form-bottom">'. drupal_render($form) .'</div>';
951
952 return $output;
953 }
954
955 /**
956 * Handle the form submit for adding a new address or editing an
957 * existing address.
958 *
959 * @param $form The form.
960 * @param $form_state The form state.
961 * @return The path where we should wind up.
962 */
963 function uc_addresses_get_address_form_submit($form, &$form_state) {
964 global $user;
965
966 $address_user = $form_state['storage']['user'];
967 $address = $form_state['storage']['address'];
968 $view = $form_state['storage']['view'];
969
970 if ($form_state['clicked_button']['#value'] == t('Delete address')) {
971 cache_clear_all();
972 drupal_goto('user/'. $address_user->uid .'/addresses/' . $address->aid . '/delete');
973 }
974
975 if (!$address) {
976 $address = new stdClass();
977 $address->uid = $address_user->uid;
978 }
979
980 $valid = TRUE;
981 foreach (element_children($form_state['values']['panes']) as $pane_id) {
982 $func = _address_pane_data($pane_id, 'callback');
983 $isvalid = $func('process', $address, $form_state['values']['panes'][$pane_id]);
984 if ($isvalid === FALSE) {
985 $_SESSION['expanded_panes'][] = $key;
986 $valid = FALSE;
987 }
988 }
989 if ($view == 'edit') { // Update database
990 _uc_addresses_db_update_address($address);
991 }
992 elseif ($view == 'new' || $view == 'add') { // Insert into datebase
993 _uc_addresses_db_add_address($address);
994 }
995
996 drupal_goto('user/'. $address_user->uid .'/addresses');
997 }
998
999 /**
1000 * Format an address the same as the rest of the Ubercart store.
1001 *
1002 * @param $items An object containing address information.
1003 * @return A formatted address.
1004 */
1005 function uc_addresses_address($items) {
1006 $address = uc_address_format(
1007 $items->first_name,
1008 $items->last_name,
1009 $items->company,
1010 $items->street1,
1011 $items->street2,
1012 $items->city,
1013 $items->zone,
1014 $items->postal_code,
1015 $items->country
1016 );
1017 return $address;
1018 }
1019
1020 /**
1021 * Display a confirmation page before deleting an address.
1022 *
1023 * @param $address_user The user who "owns" the address.
1024 * @param $address The address to delete.
1025 */
1026 function uc_addresses_delete_address_confirm($address_user, $address) {
1027 $uid = $address_user->uid;
1028 $aid = $address->aid;
1029
1030 $form = drupal_get_form('uc_addresses_delete_address_confirm_form', $address_user, $address);
1031
1032 $help =
1033 variable_get('uc_addresses_delete_instructions',
1034 t('Are you are sure you want to Delete this address? ' .
1035 'Once deleted, the address cannot be recovered.',
1036 array('!delete' => variable_get('uc_addresses_delete_button',
1037 t('Delete address')))
1038 )
1039 );
1040
1041 $panes = _address_pane_list();
1042 foreach ($panes as $pane) {
1043 if (variable_get('uc_addresses_pane_'. $pane['id'] .'_enabled', TRUE)) {
1044 $func = $pane['callback'];
1045 if (function_exists($func)) {
1046 $return = $func('view', $address, NULL);
1047 if (!is_NULL($return)) {
1048 $data[$pane['title']] = $return;
1049 }
1050 }
1051 }
1052 }
1053
1054 $output = theme('uc_addresses_address_delete_confirm', $help, $data, $form);
1055
1056 return $output;
1057 }
1058
1059 /**
1060 * Theme the address deletion confirmation form.
1061 *
1062 * @param $help The help message to display.
1063 * @param $panes An associative array for each address pane that
1064 * has information to add to the delete page. The key is the
1065 * pane's title and the value is either the data returned for
1066 * that pane or an array of returned data.
1067 * @param $form The HTML version of the form that by default
1068 * includes the 'Back' and 'Delete Address' buttons at the bottom
1069 * of the confirmation page.
1070 * @return The themed confirmation form (as a string).
1071 * @ingroup themeable
1072 */
1073 function theme_uc_addresses_address_delete_confirm($help, $panes, $form) {
1074 drupal_add_css(drupal_get_path('module', 'uc_addresses') .'/uc_addresses.css');
1075
1076 $output = '<p>'. $help .'</p>';
1077 $output .= '<div class="list_address"><table class="address-preview-table">';
1078 foreach ($panes as $title => $data) {
1079 $output .= '<tr class="pane-title-row"><td colspan="2">'. t('Address')
1080 .'</td></tr>';
1081 if (is_array($data)) {
1082 foreach ($data as $row) {
1083 if (is_array($row)) {
1084 if (isset($row['border'])) {
1085 $border = ' class="row-border-'. $row['border'] .'"';
1086 }
1087 else {
1088 $border = '';
1089 }
1090 $output .= '<tr class="pane-data-row"'. $border .'><td class="title-col" '
1091 .'>'. $row['title'] .':</td><td class="data-col">'
1092 . $row['data'] .'</td></tr>';
1093 }
1094 else {
1095 $output .= '<tr class="pane-data-row"><td colspan="2">'. $row .'</td></tr>';
1096 }
1097 }
1098 }
1099 else {
1100 $output .= '<tr class="pane-data-row"><td colspan="2">'. $data .'</td></tr>';
1101 }
1102 }
1103 $output .= '<tr class="preview-button-row"><td colspan="2">'. $form
1104 .'</td></tr></table>';
1105 $output .= '</div>';
1106 return $output;
1107 }
1108
1109 /**
1110 * Get the submit buttons to confirm deletion of a user's address.
1111 *
1112 * @param $form_state The state of the form.
1113 * @param $user The user who "owns" the address.
1114 * @param $address The address we are deleting.
1115 * @return The buttons for the form (as a string).
1116 * @ingroup forms
1117 */
1118 function uc_addresses_delete_address_confirm_form(&$form_state, $address_user, $address) {
1119
1120 $form_state['storage']['user'] = $address_user;
1121 $form_state['storage']['address'] = $address;
1122
1123 // The buttons
1124
1125 $form['submit'] = array('#type' => 'submit',
1126 '#value' => variable_get('uc_addresses_delete_button', t('Delete address')),
1127 '#suffix' => l(t('Cancel'), 'user/'. $address_user->uid .'/addresses/'));
1128 return $form;
1129 }
1130
1131 /**
1132 * Delete a user-confirmed address.
1133 *
1134 * @param $form The form.
1135 * @param $form_state The form state.
1136 */
1137 function uc_addresses_delete_address_confirm_form_submit($form, &$form_state) {
1138
1139 $address_user = $form_state['storage']['user'];
1140 $address = $form_state['storage']['address'];
1141
1142 _uc_addresses_db_delete_address($address->aid);
1143 drupal_set_message(t('The address has been deleted.'));
1144
1145 drupal_goto('user/'. $address_user->uid .'/addresses');
1146 }
1147
1148 /**
1149 * This function handles the AHAH call made when a user changes the
1150 * country selection. A new set of zone values is generated.
1151 */
1152
1153 function uc_addresses_js_util()
1154 {
1155 $country_id = intval($_POST['country_id']) > 0 ? intval($_POST['country_id']) : uc_store_default_country();
1156 $title = isset($_POST['title']) ? check_plain($_POST['title']) : NULL;
1157 $display = isset($_POST['display']) ? check_plain($_POST['display']) : 'name';
1158 $select = $zone = uc_zone_select($title, NULL, NULL, $country_id, $display);
1159
1160 // Remove DIV and SELECT tags as well as any newlines and carriage
1161 // returns from the generated HTML code
1162
1163 $select['#parents'] = array();
1164 $match = array('`<[/]*div[^>]*>`', '`<[/]*select[^>]*>`', '`\n|\r`');
1165 $replace = array('', '', '');
1166 $output = preg_replace($match, $replace, theme('select', $select));
1167
1168 // Update the cached copy of the form
1169
1170 $form_state = array('storage' => NULL, 'submitted' => FALSE);
1171 $form_build_id = $_POST['form_build_id'];
1172 $form = form_get_cache($form_build_id, $form_state);
1173 $form['panes']['address']['zone'] = $zone;
1174
1175 form_set_cache($form_build_id, $form, $form_state);
1176
1177 print $output;
1178 exit();
1179 }
1180
1181 /*******************************************************************************
1182 * Database Functions
1183 ******************************************************************************/
1184
1185 /**
1186 * Add a new address to the database table. If the address is already
1187 * in the database (for this user), it is not added.
1188 *
1189 * @param $address The address to add (as an object).
1190 * @param The id of the new address or FALSE if there was an error.
1191 */
1192 function _uc_addresses_db_add_address($address, $silent = FALSE) {
1193 global $user;
1194
1195 // If this is an anonymous user, save the address for later
1196
1197 if ($address->uid == 0 && isset($address->first_name)) {
1198 $saved_addresses = NULL;
1199
1200 if (isset($_SESSION['uc_addresses_saved_addresses'])) {
1201 $saved_addresses = $_SESSION['uc_addresses_saved_addresses'];
1202 }
1203 if (!is_array($saved_addresses)) {
1204 $saved_addresses = array();
1205 }
1206 $saved_addresses[] = drupal_clone($address);
1207 $_SESSION['uc_addresses_saved_addresses'] = $saved_addresses;
1208