Theme a multiple CCK field with a table

Sometimes CCK contrib modules cannot do exactly what you want. It’s time to build your custom CCK field!

Official documentation on CCK fields creation for Drupal 6 is incomplete and some passages are obscure. If there is a good howto you have to read before do any CCK customization, this is Creating Custom CCK Fields. This howto supposes you’ve read and understand it before continue. If you want to create a custom field, you can read the complete Creating a Compound field. A custom multiple compound field (with more than one field for element, e.g. an image and its description).

Read these howto well, you’ll spare time later

Well, you have followed the howto, you have your own compound field but now you have a problem. You want to display compound field data as cells in a table, and each field as row.

On following example, we have a name list made with a multiple compound field with “firstname” and “lastname” columns.

KarenS tell you that you’ve to use CONTENT_HANDLE_MODULE instead of CONTENT_HANDLE_CORE on hook_formatter_info() .

// The machine name of the formatter.
function my_funny_module_field_formatter_info() {
  return array(
    'default' => array(
      'label' => t('Default'),
      // An array of the field types this formatter
      // can be used on.
      'field types' => array('examplefield'),
      // CONTENT_HANDLE_CORE:   CCK will pass the formatter
      // a single value.
      // CONTENT_HANDLE_MODULE: CCK will pass the formatter
      // an array of all the values. None of CCK's core
      // formatters use multiple values, that is an option
      // available to other modules that want it.
      'multiple values' => CONTENT_HANDLE_MODULE,

/** Set the formatter **/
function my_funny_module_theme() {
  return array(
    'my_funny_module_formatter_default' => array(
      'arguments' => array('element' => NULL),
      'function' => 'funny_display_table',

/** Here you format your table data as array **/
function my_funny_module_formatter_default($element) {
  $data = array(
  return $data;

/** This function will display a table even where data array is empty:
 ** You have to put an additional control statement to avoid this.
 ** $element will have $data from formatter_default() above
function my_funny_module_display_table($element) {
  $header = array(
    t('First name'),
    t('Last name'),
  $i = 0;
  while (!$end) {
    /** Any row will contains **/
    if(array_key_exists($i, $element)) {
      $rows[] = array(
        'firstname' => $element[$i]['#item']['firstname'],
        'lastname' =>$element[$i]['#item']['lastname'],
    else {
      $end = TRUE;
  /** Theme a table with data from element and header **/
  return theme('table', $header, $rows);

Note: to format a table you have to change only “multiple values” on my_funny_module_field_formatter_info(): you can leave my_funny_module_widget_info() as is.

See also:

Howto merge two torrent files

Update 2017: The only working method is now to use Vuze’s Swarm Merging starting the two torrents at the same time. Vuze will auto-detect the uncompleted torrent files merging the two toghether. Remove .part extension of existing files if you put uncompleted files from another client.

Update October, 2010: before trying this howto, I suggest to try mergetorrent. It’s free software, released under GNU GPL by Eyal (read comments) and it’s simpler than the method described below. Thank you Eyal!

Sometimes you want to download a torrent that you’ve partially downloaded. Many bittorrent client allow partially downloaded files, but what if you’ve downloaded the same torrent twice, with differents parts available?

Use Zeroconf / Local peer

I’ve used two client on the same LAN, ktorrent (on Debian) and utorrent (on Windows XP). I’ve two downloaded files (or folder) from the same .torrent, with different parts downloaded.

  • Enable Zeroconf plugin on ktorrent
  • Check if on utorrent “Enable local peer discovery” is enabled
  • Import existing download #1 on ktorrent
  • On debian system, as root type ifconfig to discover your local IP address, i.e.  inet addr:192.168.0.XX
  • Go to ktorrent preferences and check the used port (e.g. 12345)
  • On utorrent go to Peers tab on #2 download. Right-click > Add peer
  • Type your first machine IP address (e.g. Debian) and the first bittorrent client port (e.g. 12345 on ktorrent),  e.g. 192.168.0.XX:12345 with no protocol prepended.

On both client you’ll notice a new peer, downloading and uploading very fast. Little after, the two downloaded files / folder could be completely merged.

You can now close #2 and continue to download the torrent on a single machine / client from external peers.

Note: I’ve tested this method on the same machine using Virtualbox (Debian as host, XP as guest).

See also:

Howto extract tracks from mkv and avi

This howto requires:

  • mplayer
  • mkvtoolnix
  • your Linux box 😉

Audio from Avi files (es. Xvid + MP3):

mplayer -dumpaudio "mymovie.avi" -dumpfile mymovie_audio_track.mp3

Tracks from Matroska MKV file:

List all tracks:

mkvmerge -i mymovie.mkv

File 'mymovie.mkv': container: Matroska
Track ID 1: video (V_MS/VFW/FOURCC, XVID)
Track ID 2: audio (A_VORBIS)
Track ID 3: audio (A_VORBIS)
Track ID 4: subtitles (S_TEXT/UTF8)
Track ID 5: subtitles (S_TEXT/UTF8)

mkvextract tracks *.mkv 3:mymovie_audio_track.ogg

Creates two files, mymovie_audio_track.ogg (track 3) and (track 4).

Installing Plone on Debian

A little howto to quickly install and try Plone (a GPL’d CMS based on Zope) on your linux box. Well, the installer seems to do the job nicely. 🙂

Tested on Plone 3.* version, Debian “Lenny”.

    • apt-get install g++
    • Download latest version of Plone (Unified Installer)
    • Execute:
      tar zxvf Plone-YOURVERSION-UnifiedInstaller.tgz
      cd Plone-
      ./ standalone
      gedit /usr/local/Plone/zinstance/README.txt &
      gedit /usr/local/Plone/zinstance/buildout.cfg &
      /usr/local/Plone/zinstance/bin/plonectl start
      less /usr/local/Plone/zinstance/adminPassword.txt

README should be read to follow installation instructions, then you can modify Plone configuration on buildout.cfg, and then you can start Plone. On adminPassword.txt you’ll find your Plone passwords to use for administrative purpouses.

  • Add /usr/local/Plone/zinstance/bin/plonectl start to /etc/rc.local before exit 0 (Red Hat) to run plone at any server restart or create a script on /etc/init.d/ (Debian) like.

Now you can test this CMS based on Python (I’ve tested it 4 years ago, maybe it hardly can replace Drupal but you can give it a try 😉 ).

Save user profile on Drupal

Tested on:

  • Drupal 5.x

After you have created some user fields through Profile module provided by core, you can have the need to save value into the user object. Here a quick howto to do this.

On user creation:

/** create user profile ($new_user will be an user object) */
$new_user_array = array (
  'name' => "funnyusername",
  'pass' => "MyVerySecurePassword",
  'mail' => "info@example.gom",
  'status' => 1, # status: active
$new_user = user_save(NULL, $new_user_array, $category = 'account');
/** assign values to profile fields */
$new_user_edit =  array(
'profile_surname' => "Yumemiya",
'profile_name' => "Arika",
/** create and save profile fields */
profile_save_profile($new_user_edit, $new_user, "Character ID");

Where “Character ID” is the category name for profile_surname e profile_name.

To load current user instead creating new one, you have to use

global $user;

instead a previously declared user object $new_user.

See also:


  • Using this method during a cronjob (using hook_cron) I experienced an error: profile values are passed, but not written, but only if cronjob is launched automatically, and not forced by Report screen (as admin). After some days, I discovered that it’s a permission issue.
    Add a “cronbot” user with some privileges over user (“administer user”) to allow writing even on hidden Profile field.
    On a dedicated server, with a dedicated IP, you can automatically login by IP (by IP Login module for 5.x and 6.x) the cronjob using the server IP or loopback address ( depending on server configuration (I use the first in production, the latter on local testing).

    1. Add an ip_login Profile field (single line text field, hidden field)
    2. Enable IP Login module
    3. Assign ip_login field to IP login by IP Login configuration screen
    4. Create a new role named “cronbots”, with “administer users” permission.
    5. Create a new user named “cronbot”, with “cronbots” role assigned
    6. Change the “IP login” field for “cronbot” to your server IP ( or your static IP address as listed on ifconfig on *nix servers)

    On the next automatic cron run (not force it), you’ll see the “cronbot” user logging in. On Drupal logs, the cronjob execution pass from “Anonymous” to “cronbot”, and profile fields are rightly written.
    The other way:
    Just write profile field via db_query. (You don’t want to do a weird thing like that, right? 😉 )

PEAR install quick howto on Debian Lenny: Image_Graph

Tested on Debian Lenny.

Time elapsed before a working script < 10 minutes 😉

Install PEAR installer:

# apt-get install php-pear

First, type:

pear -h

to get help.

On root shell type:

# pear install --alldeps Image_Graph

Install failed with error:

Failed to download pear/Image_Graph within preferred state “stable”, latest release is version 0.7.2, stability “alpha”, use “channel://” to install

Retype as:

# pear install --alldeps Image_Graph-0.7.2

Repeat for other alpha dependencies the same procedure, eg:

pear install --alldeps Numbers_Words-0.15.0

At last, you got:

Nothing to install

Now, you can find all installed packages on /usr/share/php.

ImageGraph is installed on /usr/share/php/Image/Graph.php.

You have to include it on your PHPs.

You can follow the Ian’s howto on:

To start using PEAR Image_Graph.

Here the result using Ian’s code on my Linux box:

Image_Graph test, using Ian code

Image_Graph test, using Ian code

Additional info:

Hosting providers (eg. HostMonster) sometimes furnish simplified PEAR installation via CPanel. So, you can use local PEAR installation for developement, and online installation for production use.


  • To check differences between local and production versions
  • To change include path! (say no to white screen!)

See also:

Howto Share VirtualBox folders

Host: Debian GNU/Linux
Guest: Windows XP

Read the user manual on Folder sharing section.

  1. Install Guest Additions (Devices > Install Guest Additions)
  2. Click on folder icon on the bottom of the VirtualBox
  3. Create a new shared folder: select a directory on Host and choose a name (e.g. my_shared_folder)
  4. On a command shell (cmd) type this command
    net use x: \\vboxsrv\my_shared_folder

Where x: is a free device letter.