Ubercart: modifying checkout panes
on
Ubercart: modifying checkout panes
hook_form_alter() to add the field and set a custom submit handler. However, while I was able to modify the form, the submit function was never called and I wasn't able to save the value of the new field to the customer's order. This is because the ubercart checkout panes don't fully utilise the FAPI.
My solution was to create a new checkout pane and to entirely recreate the billing pane by pulling in the pane contents from the ubercart module, adding my own changes and returning the merged version.
So first I created a new checkout pane by implementing the hook, hook_checkout_pane():
<?php
function mymodule_checkout_pane() {
// Replacement for standard billing address pane.
$panes[] = array(
'id' => 'mymodule_billing',
'callback' => 'mymodule_checkout_pane_mymodule_billing',
'title' => t('Billing Address'),
'desc' => t('Custom billing address fields.'),
'weight' => 2,
'process' => TRUE,
'collapsible' => FALSE,
);
return $panes;
}
?>callback - the function to call to build the pane and process it, and process - this should be set to TRUE, so your callback function is called with the 'process' operation.
For the callback function, I didn't want to just copy and paste in Ubercart's uc_checkout_pane_billing() function as then I wouldn't be able to avail of any modifications made to the original "billing information" pane by simply upgrading the module - I would have to modify my custom module each time. So for each operation, my checkout pane calls Ubercart's one, makes my custom changes and then returns the merged result. The final result is as follows:
<?php
function mymodule_checkout_pane_mymodule_billing($op, &$arg1, $arg2) {
require_once(drupal_get_path('module', 'uc_cart') . '/uc_cart_checkout_pane.inc');
switch ($op) {
case 'view':
// This is needed to avoid 'an illegal choice has been made' error.
if (isset($_POST['panes']['mymodule_billing']['billing_country'])) {
$_POST['panes']['billing']['billing_country'] = $_POST['panes']['mymodule_billing']['billing_country'];
}
$contents = uc_checkout_pane_billing($op, $arg1, $arg2);
// Add 'title' or 'salutation' to billing address details.
$contents['contents']['billing_title'] = array(
'#type' => 'select',
'#title' => t('Title'),
'#options' => array('Mr', 'Mrs', 'Ms', 'Miss', 'Dr', 'Fr', 'Rev', 'Sr'),
'#required' => TRUE,
'#weight' => 0,
'#default_value' => $arg1->data['billing_title'],
);
// Address history selector doesn't work for this solution, so remove it.
unset($contents['contents']['billing_address_select']);
return $contents;
case 'review':
return uc_checkout_pane_billing($op, $arg1, $arg2);
case 'process':
$arg1->billing_title = $arg2['billing_title']; // Save our custom field.
return uc_checkout_pane_billing($op, $arg1, $arg2);
}
}
?>Hi, tnx for your perfect tutoria! Could you give also some advice to display (and mybe update) the field also on the on order admin backend? Ex. I have a text field where customer instert his mobile number to receive sms. With your module i display the field on checkout.
I want to see also this field on the admin order review and maybe ( for example if the number is wrong) update it directly from admin order review. Do you think it's possible?
This article describes almost exactly what I need to do, but I do not entirely understand how to implement it, as to this point I have only configured Drupal. I have never written a line of php code. I did figure out to put the code into a file with the extension ".module", created a ".info" file, and was able to enable the module without syntax errors.
It also does something, because when I get to the checkout page, it now renders a blank page. If I disable the module, the checkout page displays as before.
The only modifications I made to the source was to replace "mymodule" with a real module name, and changed the added field type to 'text'. I put the module in a folder at the same level as ubercart, i.e. under sites/all/modules/.
Not having any real experience with php, I do not really know where to begin as far as debugging this problem.
Any suggestions would be appreciated.
Ok, found the first problem. Apparently one cannot leave white space after the '>' closing the php code. I removed that, and now the checkout form displays, but without the added field. I made a couple of what I thought to be trivial changes. I then put the code in verbatim as displayed in the example, but again do not get the added field.
The log file shows nothing. I did get one odd error in the log file the first time I implemented the module with the original text, but attributed to the anonymous user. An anonymous user cannot get to the checkout page. It said "failed opening" the module just created from bootstrap.inc line 617. Other than this one instance, I have not been able to reproduce it.
Is there anything in particular I need to do with the naming of the module, something in info file, or something like that. I don't even know where to look to begin to debug this.
Thanks,
Eric
I see one problem, when it said "the final result is...", I assumed that meant the second set of code replaced the first. But now I see that it calls it.
I put the second block of code in the module file. I then tried putting the first block of code in the same module file. This simply resulted in getting a second instance of the billing panel displayed, but again without the extra field.
Where does this code go? In what file and what folder?
Thanks,
Eric
In your code, you make the comment "Address history selector doesn't work for this solution, so remove it" and then unset the relevant array element. It's actually pretty easy to fix the address history selector so that it will continue to work--though there is an additional cost to doing so :)
To fix it, you'll change the code as indicated:
// 1. Replace "'id' => 'mymodule_billing'" with "'id' => 'mymodulebilling'" in mymodule_checkout_pane()
// 2. Replace all existing instances of "mymodule_billing" with "mymodulebilling" in mymodule_checkout_pane_mymodule_billing();
// 3. Change this line:
//$contents = uc_checkout_pane_billing($op, $arg1, $arg2);
// To this:
$temp_contents = uc_checkout_pane_billing($op, $arg1, $arg2);
// 4. Add the following lines:
$contents = array('contents' => array());
foreach($temp_contents['contents'] as $key => $value) {
$contents['contents']['mymodule'. $key] = $value;
}
$contents['contents']['mymodulebilling_address_select']['#attributes']['onchange'] = "apply_address('mymodulebilling', this.value);";
These changes make the keys of the array in $contents['contents'] take the form "mymodulebilling_title" instead of "billing_title". This in turn will cause the markup in the relevant checkout pane to match the value used in the onchange attribute of the address select (the removal of underscores may not be necessary, but when I tried with the underscores, the javascript failed...but it could easily have been something else I did at the same time...)
As for the additional cost, Ubercart will no longer style this particular pane as a table, so if you want to use this solution, you have to be willing to re-theme the new checkout pane or to live with it :) The id attributes of the form element wind up being somewhat ridiculous too; they look like this: 'id="edit-panes-mymoduledelivery-mymoduledelivery-street"'.












Hi,
I used this code to add a VAT field to my billing information.. but stumpled upon three things: