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.
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(
'code_entered' => 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.
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().
----
After writing this I found this blog post which also looks quite useful.