Friday 6 February 2009

Beginning to see how Drupal works

I have been looking at Drupal on and off for about 6 months now and it has always seemed to be abit mysterious in the way it works.
I read alot about it and tried to figure out how it worked but it just wasn't going in. Drupal is the first CMS system that I have looked into in any depth so I thought it would take time to see how the system works.

Finally yesterday it clicked. Now some fundamental concepts have started to sink in.
  • Each module has fuctions in it that are used to create the path to a drupal page and links to the page. (xxx_menu)
  • Each module has a function to create the form (xxx_form).
  • Each module has a function called xxx_form_submit that runs when the form is submitted. It uses a parameter called form_values that is automatically set with the values from the form. For example form_values['textboxname']
This maybe basic information. But it is information that I found hard to find.

Other information that I found useful is:
  • global $user is used to retreive information about a user from anywhere on a site.
  • Two types of menu types that I have used are MENU_LOCAL_TASK and MENU_CALLBACK. MENU_LOCAL_TASK is used to create a tab style link to a page. Like 'View' and 'Edit' tabs at the top of most drupal pages. MENU_CALLBACK is used when displaying a form and has setting for setting up parameters for a form.
  • Remember that most things are arrays.
Below is the module I have created after it 'clicked'. I have much much more to learn about Drupal so this module many not be exactly right but having this basic knowledge has made a big difference to me and a post like this would have helped me when I started to look into Drupal module development. This module will need Ubercart installed in order to work correctly.

The background to this module is that I required users to be able to send an older version of the product to my client after they bought a new version of the product. When they send in the old unit they will receive a rebate from the client.

This module allows a user to click on an order then pick a product from the order that they want to send to the client. The customer can choose to have the product picked up or send it in themselves. Once they submit the form it will send in information to the client that a unit is going to be sent it.
uid) {

$items[] = array(
'path' => 'user/'. arg(1) .'/returns/'. arg(3),
'title' => t('Order @order_id', array('@order_id' => arg(3))),
'description' => t('View order @order_id.', array('@order_id' => arg(3))),
'callback' => 'drupal_get_form',
'callback arguments' => array('returns_form', arg(3), 'customer'),
'access' => user_access('view all orders') || $user->uid == arg(1),
'type' => MENU_CALLBACK,

$items[] = array(
'path' => 'user/'. arg(1) .'/returns',
'title' => t('Returns'),
'description' => t('View your returns history.'),
'callback' => 'returns_history',
'callback arguments' => array(arg(1)),
'access' => user_access('view all orders') || $user->uid == arg(1),
'type' => MENU_LOCAL_TASK,
return $items;

* Returns the sortable table listing of a customer's orders.
* @param $uid
* The user ID whose orders you wish to list.
function returns_history($uid) {
drupal_set_title(t('Returns history'));

$header = array(
array('data' => t('Date'), 'field' => 'o.created', 'sort' => 'desc'),
array('data' => t('Order #'), 'field' => 'o.order_id'),
array('data' => t('Status'), 'field' => 'os.title'),
array('data' => t('Products'), 'field' => 'products'),
array('data' => t('Total'), 'field' => 'o.order_total')

$result = pager_query("SELECT o.order_id, o.created, os.title, SUM(op.qty) AS products, o.order_total AS total FROM {uc_orders} AS o LEFT JOIN {uc_order_statuses} AS os ON o.order_status = os.order_status_id LEFT JOIN {uc_order_products} AS op ON o.order_id = op.order_id WHERE o.uid = %d AND o.order_status IN ". uc_order_status_list('general', TRUE) ." GROUP BY o.order_id, o.created, os.title, o.order_total". tablesort_sql($header), 20, 0, "SELECT COUNT(*) FROM {uc_orders} WHERE uid = %d AND order_status NOT IN ". uc_order_status_list('specific', TRUE), $uid);

// Build a table based on the customer's orders.
while ($order = db_fetch_object($result)) {
$link = l($order->order_id, 'user/'. $uid .'/returns/'. $order->order_id);
if (user_access('view all orders')) {
$link .= '
'. uc_order_actions($order, TRUE) .'';
$rows[] = array(
array('data' => format_date($order->created, 'custom', variable_get('uc_date_format_default', 'm/d/Y'))),
array('data' => $link, 'nowrap' => 'nowrap'),
array('data' => $order->title),
array('data' => (!is_null($order->products) ? $order->products : 0), 'align' => 'center'),
array('data' => uc_currency_format($order->total, TRUE), 'align' => 'right'),

$output = theme('table', $header, $rows) . theme('pager', null, 20, 0);

return $output;

* Display the order view screen, constructed via hook_order_pane().
function returns_form($order_id, $view = 'view') {

$order = uc_order_load($order_id);
$form = array();

if ($view == 'customer') {
$breadcrumb = drupal_get_breadcrumb();
$breadcrumb[2] = l(t('Returns history'), 'user/'. arg(1) .'/returns');

if ($order === FALSE) {
drupal_set_message(t('Order @order_id does not exist.', array('@order_id' => $order_id)));

$partslist = array();
$result = db_query("SELECT title FROM {uc_order_products} order_id = %d ORDER BY order_product_id", $order_id);
while ($product = db_fetch_object($result)) {
$partslist[$product->title] = $product->title . ' ' . $product->surchargecode;

$form['parts'] = array(
'#type' => 'checkboxes',
'#title' => t('Part numbers'),
'#options' => $partslist,
'#description' => t('Select the old units that you will be sending to us'),

$options = array('0' => t('Please arrange collection for me'), '1' => t('I will send the items myself'));
$form['collection'] = array(
'#type' => 'radios',
'#title' => t('Collection details'),
'#default_value' => 0,
'#options' => $options,
'#description' => t('How would you like to get the old units to us.'),

$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Send'),

return $form;

function returns_form_submit($form_id, $form_values)
global $user;

$from = $user->mail;
$recipient = '';
$subject = t(' Collection Request');
$bodytext = 'Old Unit';

if ($form_values['collection'] == 0)
$bodytext .= "\n\nFor Collection";
$bodytext .= "\n\nCustomer Will Send";

$bodytext .= "\n\nParts";

foreach($form_values['parts'] as $key => $element){
$bodytext .= "\n\n$element";

$body = t($bodytext);

if(drupal_mail('returns-email', $recipient, $subject, $body, $from)){
drupal_set_message(t('Your message has been sent. We will be in touch soon'));
drupal_set_message(t('Your message has NOT been sent.'));



I hope this works. If you find it useful or you have an issue running it then leave a comment. I am currently running this system on Drupal 5 with Ubercart.

1 comment:

Drupal Dedicated Hosting said...

I was looking for crucial information on this subject. The information was important as I am about to launch my own portal. Thanks for providing a missing link in my business. Selecting a Content Management System is extremely influential long term I have used Drupal. Because SinceI found out the most popular media sites including Men's Health and Maxim use Durpal, everything clicked For hosting I chose GetPantheon including features like the capability to go live with 1 click which CMS have you used?