As I get more and more familiar with the Azure platform, one thing that strikes me more than anything else is that Azure is is not an all or nothing thing.  You can use the Azure platform as a component of your overall solution, or you can take advantage of individual services provided by the platform.  It is not a case of choosing your technology or vendor and then designing the solution - you can design your solution and choose your platform.

I previously wrote a simple application using open source technology and deployed it wholly within the Azure platform.  You can read about it here.  This got me thinking about the other end of the spectrum:  writing and hosting and application on an open source platform, but making use of Azure for one small component.

The challenge I set myself was to write a Drupal module (I have been wanting to do this for a while now), but to use Microsoft Dallas as the data source.

Drupal is an open source content management system (CMS) written in PHP. It is used as a back-end system for many different types of websites, ranging from small personal blogs to large corporate and political sites. It is also used for knowledge management and business collaboration. 

Microsoft® Codename "Dallas" is a new service allowing developers and information workers to easily discover, purchase, and manage premium data subscriptions in the Windows Azure platform. Dallas is an information marketplace that brings data, imagery, and real-time web services from leading commercial data providers and authoritative public data sources together into a single location, under a unified provisioning and billing framework. Additionally, Dallas APIs allow developers and information workers to consume this premium content with virtually any platform, application or business workflow

The module is very simple:

  • it connects to a predefined Microsoft Codename 'Dallas' service on Windows Azure;
  • Retrieves UNESCO data relating to UK Government expenditure on Education;
  • renders the data as a Drupal block;
  • allows the block to be positioned on the portal using the administrative interface.

There are a number of parameters that can be set on the Dallas request to filter the returned results (such as for paging or to bring back data for a specific country) or to request a specific format for the returned results (such as ATOM, etc).

To keep things simple I accepted the defaults and specified UK hard coded in the request.

dallas_module_2_659356C2

A Drupal module is a common way of extending Drupal.  A module is  by collection of functions that link into Drupal, providing additional functionality to your Drupal installation.  I followed this tutorial to get started.

All modules must have a modulename.info file, which contains meta information about the module. My module is called dallas_module and is described in dallas_module.info like this:

;$Id
$name = Dallas
description = A block module that uses Microsoft's Codename Dallas on Windows Azure
core = 6.x

Drupal's module system is based on the concept of "hooks". A hook is a PHP function implements a Drupal interface defined by convention.  A that is named foo_bar(), where "foo" is the name of the module (whose filename is thus foo.module) and "bar" is the name of the hook. Each hook has a defined set of parameters and a specified result type.

To extend Drupal, a module simply implements hooks. When Drupal wishes to allow intervention from modules, it determines which modules implement a hook and calls that hook in all enabled modules that implement it.  My module is implemented by PHP code stored in dallas_module.module. For a really simple module like this there is not much you need to implement:

<?php
// $Id$
// provide help for module installation
function dallas_module_help($path, $arg) {
	$output = '';  //declare your output variable
	switch ($path) {
	        case "admin/help#dallas_module":
	            $output = '<p>'.  t("Tests Dallas on Windows Azure") .'</p>';
			break;    
	}    
	return $output;
}
// define required permissions
function dallas_module_perm() {
	return array('access dallas_module content');
}
// render a block
function dallas_module_block($op='list', $delta=0) {
// This is where the code will go…
}

The code to retrieve the data and render it as a table is all contained within the dallas_module_block function.

Firstly set up a variable relating to the query that you want to run.  The UNESCO service for government expenditure has the following URI:

$request = 
'https://api.sqlazureservices.com/UnService.svc/UNESCO/XGOVEXP/
	?ref_area=GBR
	&$format=atom10';

The ?ref_area parameter denotes UK and the $format parameter denotes the required format for the returned data.  (obviously you could retrieve the possible values for these parameters and use them in drop down lists - but that's not what I am trying to learn here).

Next I set two variables for the account key and user id for my Dallas account. (These are mangled).

$accountKey = 'e999999993YdX9SyUkA988p71orM=';
$uniqueUserID = '626999999-b530-4999999999';
$acc = "\$accountKey: " . $accountKey;
$uid = "\$uniqueUserID: " . $uniqueUserID;

I used 4 lines rather than two, to get around a problem building the headers array that follows (but I don't really understand why I needed to do it).  Then I added the headers to the request:

$headers = array($acc, $uid); 
$opts = array('http'=>array('method'=>"GET",'header'=>$headers)); 
$context = stream_context_create($opts);

Then I retrieved the data using file_get_contents():

$response = file_get_contents($request, false, $context)

Then I added some basic error handling based on the http status code returned as part of the response:

// Retrieve HTTP status code
list($version,$status_code,$msg) = explode(' ',$http_response_header[0], 3);
// Check the HTTP Status code
switch($status_code) {
	case 200:
		// Success
		break;
	case 503:
		die('Service unavailable');
		break;
	case 403:
		die('Forbidden');
		break;
	case 400:
		die('Bad request. The exact error is returned in the XML response.');
		break;
	default:
		die('unexpected HTTP status of:' . $status_code);
}

Then parse the response into two variables ($title and $arr are used to display the data in the block):

$xml = simplexml_load_string($response);
$title= (string) $xml->title;
$arr = array();
foreach ($xml->entry as $entry) {
	$ns_props = $entry->content->children(
		'http://schemas.microsoft.com/ado/2007/08/dataservices/metadata');
	$year="";
	$spend="";
	foreach ($ns_props->children(
		'http://schemas.microsoft.com/ado/2007/08/dataservices') 
		as $child) {
			switch ($child->getName()) {
				case "timePeriod":
					$year = $child;
					break;
				case "observationValue":
				$spend = $child;
				break;
			}
			if($year <> "" && $spend <>"") {
				$arr["$year"] = floatval($spend);
			}
	}
}

Finally, render the data returned from dallas as Drupal block output. 

$block_subject .= "<a href=\"Dallas" 
	_mce_href="http://www.microsoft.com/WindowsAzure/dallas/\">
	Dallas">http://www.microsoft.com/WindowsAzure/dallas/\">
	Dallas Block</a>";
$block_content .= '<p>This is a simple application ....</p>';
$_SESSION['graphdata']=serialize($arr);
$_SESSION['graphtitle']=serialize($title);
include_once 'util.php';
$block_content .= util_print();
// check to see if there was any content before returning
// the block view
if ($block_content == '') {
	// no content from a week ago
	$block['subject'] = 'Dallas Module';
	$block['content'] = 'Sorry No Content Yet!';
	return $block;
}
// set up the block
$block['subject'] = $block_subject;
$block['content'] = $block_content;
return $block;

This is a slightly weird way to do this.  I was trying to graph the results using PHPGraphLib, but I was spending more time debugging the graph library on Drupal than testing my application.  This is why the data is passed to another PHP file in session.  The util.php file has the following code to render the block:

<?php
function util_getTitle() {
	return unserialize($_SESSION['graphtitle']);
}
function util_getData() {
	return unserialize($_SESSION['graphdata']);
}
function util_print() {
	$retval = '<b>' . util_getTitle() . '</b><br/>';
	$retval .= '<table><tr><td>Year</td><td align="right">Percentage</td></tr>';
	foreach (util_getData() as $key => $value) {
		$retval .= '<tr><td>' . $key . '</td><td align="right">' . number_format($value,2) . '</td></tr>';
	}
	$retval .= '</table>';
	return $retval;
}
?>

All that remains is to deploy the module.  This is a simple case of copying your module to the sites/all/modules directory for your Drupal installation, and then enabling the module through the Drupal Administration interface. 

And that's it.  This is all the code you need to access Dallas data and render as a Drupal block.  Of course it’s not very functional and the block does not support Drupal themes, but it’s easy to see how Dallas data could be incorporated into applications based on a wide range of technologies, and how the data could be blended with other techniques (such as mapping) to provide some interesting new services.

You can see the block running on my Drupal Site.

 

Written by Nick Hill