drupal

An overview of site building in Wedful (Drupal install profiles, Aegir, and features)

7 comments

This post is just to give an overview of some of the techniques we use to build our Wedful websites product. I'll be discussing most of the things listed here in more detail in later posts as well, but thought this would make a good starting point.

Every single wedding website is a complete Drupal site, they don't share users or any data with any other wedding sites. We wanted to go this route so that each site had complete control over it's theme and domain name among other things. It also allows us to balance our server load by moving very active sites to servers with more resources.

Adding a simple twitter feed to your Drupal site

10 comments

I just added a simple twitter feed to one of my sites and thought I'd share what I did. The only other post I could find about was this one http://drupal.org/node/151185 and I didn't really think it should be necessary to write any code (and especially not any db queries) views could do all the display stuff I needed.

Quick DrupalCon DC Wrapup AND a mystery!

6 comments

Last week was DrupalCon DC. This was my 4th DrupalCon in a row... Barcelona, Boston, Szeged, and now Washington, DC. The NowPublic development team is distributed throughout North America and Europe, so the bi-annual DrupalCon is the only time we all (or most of us at least) are able to get together. Though the whole team couldn't make it this time around it was still good to see the guys that were able to.

We ended up staying in 4 bedroom house with 8 "beds" and 11 people. All in all a great time, and I managed to avoid the conference flu that tends to spread through conferences at this time of year (which is the first time I've done so in 3 years :) ).

The conference was very well organized, my only complaint would have been the internet... you should make sure it's working /before/ bragging to everyone about it.

I actually went to more sessions this time around than normal, but still have very little to write about. Did a bit of sight seeing while I was there, but the US DrupalCon's seem to just be a bit less of a party and more of a conference than their European counterparts... go figure.

Now for the mystery! Can you guess what this is?

New Year - New Theme

no comments

Hey! I have a new theme!

The theme was designed and implemented by Sam in her spare time. She spent a lot of time getting even the littlest details worked out and I'm super grateful for all her work on it. So thank you Sam, you really are awesome!

My blog runs on Drupal 6, though up until this past summer it was running on WordPress. I use this site to experiment with ideas and mostly just play around with it, so occasionally you may get a php error or something, please let me know if you hit one.

A screenshot of the blog, for those stuck in RSS

Over the next little while I'll be posting about individual hacks and modules I've added to the site. Currently, one of the cooler features is that I get an IM on my google talk account every time someone comments. This is using the XMPP framework with some patches I've submitted, more on that in another post.

If you're looking for a Drupal developer to do some work for anything from theming to a full Drupal website build, please feel free to contact Sam. I strongly recommend her.

Creating Custom Triggers in Drupal

27 comments

So after playing around for several hours tonight trying to build my own custom trigger I think I've finally figured it out. I thought I'd post it here for reference.

Though triggers are included in core in Drupal 6 it seems they're very poorly documented. The extent of the documentation I could find was on this trigger page in the handbook. Pro Drupal Development also has a chapter on it but unfortunately isn't really explicit enough for me with some parts.

Disclaimer: I don't really know what I'm doing, so please let me know if I've done anything wrong.

Prereqs:

  • Drupal 6
  • The triggers module should be enabled.
  • A commenter also pointed out that the triggerunlock module is also necessary. If you have your own custom actions this isn't needed though.
  • If you're following this example, you'll also need to CCK type called 'script'.

What I want to do is create a custom trigger in my module. Let's say I want to execute a custom action on my server whenever a node of a type script (as defined in the 'script' module) is created. The first step is to define hook_hook_info.

/**
 * Implementation of hook_menu_alter().
 */
function script_hook_info() {
  return array(
    'script' => array(
      'script' => array(
        'insert' => array(
          'runs when' => t('After script is created'),
        ),
      ),
    ),
  );
}

This will create a new tab in my triggers page that will be named after the name of my module as set in my .info file.

Two things I still need to do to make sure this trigger actually does anything... define hook_script and call it from a module_invoke or module_invoke_all whenever the triggering event happens and call the actions using actions_do(). Since these hooks should be executed on node insert I'll need to use hook_nodeapi().

/**
 * Implementation of hook_nodeapi().
 */
function script_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
    case 'insert':
      module_invoke_all('script', 'insert', $node);
      break;
  }
}

The second aspect (calling the associated actions) requires an implementation of hook_script() (the alternative being to just replace the module_invoke line with this functions body.

/**
 * Implementation of hook_script().
 */
function script_script($op, $node) {
  $aids = _trigger_get_hook_aids('script', $op);
  $context = array(
    'hook' => 'script',
    'op' => $op,
    'node' => $node,
  );
  actions_do(array_keys($aids), $node, $context);
}

The first line in the function is a call to _trigger_get_hook_aids which returns the list of action ID's that have been assigned to this trigger. This is a private function, but seems to be the only way to get the list of actions. The last line in the function calls actions_do(), which processes all the actions assigned to this trigger.

In this particular example you'll need a custom content type called 'script'.

And that's all there is to creating your own custom triggers.

Alternatively, I don't need to create a hook for the trigger, instead I could just piggyback off of the nodeapi hook, since this is a node operation.

The hook_hook_info looks a little different with:

function script_hook_info() {
  $info['script'] = array(
    'nodeapi' => array(
      'script' => array(
        'runs when' => t('After script is created'),
      ),
    ),
  );
  return $info;
}

And then just a slight change to hook_script() to change the hook from 'script' to 'nodeapi'.

/**
 * Implementation of hook_script().
 */
function script_script($op, $node) {
  $aids = _trigger_get_hook_aids('nodeapi', $op);
  $context = array(
    'hook' => 'nodeapi',
    'op' => $op,
    'node' => $node,
  );
  actions_do(array_keys($aids), $node, $context);
}

One other thing that was bugging me with triggers was the inability to only use them on specific cck types. There's no way to setup a trigger to only get called when an event happens to a single content type (without using the workflow module, which I found has some problems using variables in actions). Put an "if ($node->type == 'script')" somewhere appropriate, in my code I'd wrap that around the call to module_invoke_all(), for example:

function script_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  switch ($op) {
    case 'insert':
      if ($node->type == 'script') {
        module_invoke_all('script', 'insert', $node);
      }
      break;
  }
}

----

After writing this I found this blog post which also looks quite useful.

I've made some updates to this example, so hopefully it will work for everyone now.

You can download the example module here.