Drupal 6 Ubercart hook_uc_checkout_complete and content_profile

By shane
Wed, 2012-10-31 16:47

Share with Others

On a recent Drupal 6 multi-currency Ubercart website I came across the following requirements.

  • I needed to save a users preferences to determine whether to display prices with VAT or not
  • I needed the user to be able to manage these preferences from within their account settings
  • When the user purchased something, either for the first time, or multiple times, I needed their preferences to be updated

In this post I will go over part of my solution to solve these requirements. My implementation is just one of many ways that I thought about building this solution out. Here is what I did.

Drupal 6 content_profile module

I installed the Drupal 6 content_profile module and created a simple preferences content type for storing a users preferences. The main field of note here is a country field (I had other fields in the content type). To ensure that the field contained the correct Ubercart countries and the correct numeric values, I used the following PHP to build out the available options. Note: I broke this out into a function inside a custom module and just called the function inside the available options PHP code section. Most of this code was borrowed directly from the Ubercart module.

$order_by = 'country_name';
$result = db_query("SELECT * FROM {uc_countries} WHERE version > 0 ORDER BY country_name");
$options = array();
while ($country = db_fetch_array($result)) {
  $options[$country['country_id']] = ($order_by == 'country_name') ? t($country[$order_by]) : $country[$order_by];
if (count($options) == 0) {
  $options[] = t('No countries found.');
return $options;

Implementing the hook_uc_checkout_complete Ubercart hook

The next step was to make sure that if a user checked out of the store, that their preferences would either be updated (if they already existed) or created (if this is a new user). This way, when a user logs back into the site, they will see the prices as they originally have specified based on their country. I was originally going to use hook_order, but decided instead that the hook_uc_checkout_complete hook was the much easier solution. Here is an example of my hook_uc_checkout_complete implementation that updates or creates a "preferences" content type based on the orders billing country.

 * Implements hook_uc_checkout_complete().
function MYMODULE_uc_checkout_complete($order, $account) {
  // Get the nid of the existing preferences node.
  $sql = "SELECT n.nid FROM {content_type_preferences} ctp
    INNER JOIN {node} n ON ctp.nid = n.nid
    WHERE n.uid = %d";
  $result = db_fetch_object(db_query($sql, $account->uid));
  // Check if the user has a preferences node created.
  if (isset($result->nid)) {
    // Load the full node object.
    $node = node_load($result->nid);
    // Set the country field.
    if (isset($country)) {
      $node->field_country[0]['value'] = $order->billing_country;
    // Set other fields if needed.
    // Save the updated node.
    $node = node_submit($node);
  else {
    // We need to create a new preferences node.
    $node = new stdClass();
    $node->type = 'preferences';
    $node->title = $account->name . 'Preferences';
    $node->uid = $account->uid;
    $node->name = $account->name;
    $node->comment = 0;
    $node->promote = 0;
    // Set the country fields value.
    if (isset($country)) {
      $node->field_country[0]['value'] = $order->billing_country;
    // Set other fields values if needed.
    // Create the node.
    $node = node_submit($node);

Additional notes

I also added some settings to the users $_SESSION variable to handle displaying things for anonymous users. I won't go into all that detail here, but it is an important note.

hook_uc_checkout_complete and content_profile conclusion

The above was only a small part of my total solution to get this working but was one of the most important pieces to the puzzle. If you need an example on how the hook_uc_checkout_complete Ubercart hook can be used or how to create a content_profile node programmatically, the above code should be able to help you out.

Any questions or comments? Let me know below.