Live graphical stats for php-gtk.eu with Drupal

Submitted by Frederic Marand on

The PHP-GTK community site has been running on Drupal 5 betas since its creation one month ago, and I thought it really needed a live chart of statistics to match its glorious Garland dress, and GD would allow it. But how does one go about creating charts within Drupal ?

PHP-GTK graphical stats.

The image above is the live image I'm describing in this post.

Inserting the image link

Actually there's nothing special to that part. Supposing a page, say http://www.php-gtk.eu/site/access-stats needs a graph of some data, in this case Drupal stats taken from the accesslog table. All it takes is a piece of code in a module generating the image, and a simple img element in the page source, pointing to that dynamically generated image.

In this case, the link is a plain <img src="http://php-gtk.eu/gtkphpnet/stats.png" alt="PHP-GTK graphical stats" />, the path to which lets us guess it is actually handled by the gtkphpnet module.

Creating the image in a module

The interesting part is this one: how does one go about creating a live image within drupal ? After all, Drupal themes output, and image files have to be exact binary representations, served with the proper content type.

Going full-page

The only trick here is to avoid Drupal serving the rest of the page, before and after the output of our module.

Looking at the page-serving mechanism, Drupal obtains module output in order to theme it from the menu system : it invokes modules from the callback parameter in menu items within hook_menu implementations. When it obtains the output from the module, it proceeds to theme it.

Now, if the module never returns, Drupal won't receive the output, and won't theme it. The screen output will be exactly what our module has emitted (and not what it has returned , as ought to be the case for a normal themable output).

Telling the browser the content is an image

From then on, everything is just plain GD. The only notable part if the fact that the module must define the content type to match the format of the image being generated, otherwise the default text/html will be used, and not all browsers will recognize the image for what it really is.

The syntax is simple. just use the Drupal header wrapper: drupal_set_header, like:

<?php
  drupal_set_header
("Content-type: image/png");
?>

making sure that the type you'll be sending matches the format of the image you are generating. Some browsers, like Opera and MSIE, actually override the headers if they recognize the format, but Firefox 1.5 uses the content-type it receives if one is available, causing erroneous displays looking like PNG or GIF89a followed by junk.

The documentation for the GD functions is available on PHP.net at http://www.php.net/gd.

The request to obtain the data is just:

    SELECT
      DATE(FROM_UNIXTIME(al.timestamp)) ladate,
      count(DATE(FROM_UNIXTIME(al.timestamp))) cnt
    FROM {accesslog} al
    GROUP BY
      DATE(FROM_UNIXTIME(al.timestamp))';

As to the plotting code, you can just use the code at http://www.phpbuilder.com/columns/wiesendanger20001218.php3?page=6, replacing the

<?php
$data
= array( [...]
?>

part with the results from your query.

Since their example is directly usable, I think it's better for you to obtain it from them. My module is different, but has been inspired by it to a large extent, so I think I must refrain from publishing it, to avoid a potential copyright claim.