1. Writing actions and conditions
Modules may provide further actions and conditions.
One has to implement hook_action_info() and/or hook_condition_info() to specify some meta information about the actions / conditions.
Here an example for an condition.
<?php
/*
* Implementation of hook_condition_info()
*/
function yourmodule_condition_info() {
return array(
'yourmodule_condition_example' => array(
'#label' => t('Compare two users'),
'#arguments' => array(
'user1' => array('#entity' => 'user', '#label' => t('First user to compare')),
'user2' => array('#entity' => 'user', '#label' => t('Second user to compare'))
),
'#description' => t('Evaluates to TRUE, if both compared users are the same user account.'),
'#module' => t('User'),
),
);
}
?>For actions it works the same way. E.g.:
<?php
/*
* Implementation of hook_action_info()
*/
function yourmodule_action_info() {
return array(
'yourmodule_action_node_set_author' => array(
'#label' => t('Set the content author'),
'#arguments' => array(
'node' => array('#entity' => 'node', '#label' => t('Content')),
'author' => array('#entity' => 'user', '#label' => t('User, which is set as author')),
),
'#module' => t('Node'),
),
);
}
?>Arguments are:
- #label is for defining a human readable name of the action or condition.
- #arguments specifies the arguments that the action or condition requires at execution time.
- The arguments define the needed arguments of the conditon / action. It's comparable with a function signature.
- The #entity property specifies the "entity type" of the argument. Known entity types are node, user or comment.
- Have a look at the action_info / condition_info reference for a closer description of all available properties.
- #module is used for ordering the condition/action in the dropdown list while add/edit a configuration
Let's show how the example 'Set the content author' would be implemented:
<?php
/*
* Modifies a node as configured
*/
function yourmodule_action_node_set_author($node, $author) {
$node->uid = $author->uid;
$node->name = $author->name;
return array('node' => $node);
}
?>$node and $author are the two arguments as specified, which are passed to your implementation.
Saving entities
Workflow-ng can care for saving modified entities for you. This ensures that entities are saved only as often as really necessary. To do so return an associative array of arguments to save, where the keys are the arguments name and the values the modified entity. This example returns $node to be saved after execution.
Workflow-ng currently supports saving of nodes and comments. Saving users is not supported, as this isn't possible cleanly with drupal 5's user_save() function. So actions modifying user objects, have to save them self.
Also have a look at the page Adding further entity types to see how you can extend the list of supported entities.
A more advanced example
So let's have a look at a bit more advanced action, the action "Show a configurable message on the site" provided by workflow-ng.
<?php
/*
* Implementation of hook_action_info()
*/
function workflow_ng_ui_action_info() {
return array(
'workflow_ng_action_drupal_message' => array(
'#label' => t('Show a configurable message on the site'),
//we are not working with defined arguments, instead we make use of all available arguments
'#arguments' => array(),
'#module' => t('System'),
),
);
}
?>So far there is nothing new. But this action is different. First of it's configurable, and second it makes use of *all* available arguments for token replacements, which isn't specified in hook_action_info(), because it isn't necessary to do so.
The configuration form settings are passed to the action's implementation as last parameter. If there are any defined arguments, they are passed first. The two parameters $arguments and $log are also passed to every action, but aren't important in most cases.
<?php
/*
* Action Implementation: Show a configureable message
*/
function workflow_ng_action_drupal_message($settings, &$arguments, &$log) {
extract( workflow_ng_token_replace_all(array('message'), $settings, $arguments, $log) );
drupal_set_message($message, $settings['error'] ? 'error' : 'status');
}
?>The argument parameter is workflow-ng's data structure containing all the available information about the available arguments. This action uses them, to provide the token replacements. $log can be used, to write to workflow-ng's internal log, which is only useful for debugging.
Configuration Form
So let's look at configuration form. This will be called if the action is edited and the returned form will be appended to the action configuration form. Again the second parameter $argument_info is only needed, because this action makes use of all available arguments. Actions that don't do so, don't need it and may omit this parameter.
<?php
/*
* Action "Show a configureable message" configuration form
*/
function workflow_ng_action_drupal_message_form($settings = array(), $argument_info) {
$form = array();
$form['message'] = array(
'#type' => 'textarea',
'#title' => t('Message'),
'#default_value' => $settings['message'],
'#description' => t('The message that should be displayed.'),
);
workflow_ng_token_replacement_help($form, $argument_info);
$form['error'] = array(
'#type' => 'checkbox',
'#title' => t('Display as error message'),
'#default_value' => $settings['error'],
);
return $form;
}
function workflow_ng_action_drupal_message_submit($form_id, $form_values) {
//returns the needed settings
$settings = workflow_ng_token_get_settings(array('message'), $form_values);
return $settings + array('error' => $form_values['error']);
}
?>The actions submit handler has to return an array of it's settings. This array will be passed to the action on execution time.
Form Validation
Of course you can also validate the configuration form. To do so implement ACTION_validate($form_id, $form_values, $form) and use form_set_error as usual. E.g.
<?php
function workflow_ng_action_drupal_message_validate($form_id, $form_values) {
form_set_error('message', 'dummy validation error');
}
?>About the token integration..
Like the above example, you can easily make your actions and conditions token enabled. Like the above example, it suffices if you use all three API functions provided by workflow-ng:
workflow_ng_token_replacement_help($form, $argument_info)
This function just places the token replacement help into the form array as well as variables, needed by other API functions later.
workflow_ng_token_get_settings(array('message'), $form_values)
This function returns an array of settings, which is suitable for returning the settings in your form submit handler. It determines which entities are used for token replacements and adds this to the settings - so that the runtime replacement is able to use this information. Pass a list of token enabled form elements as first parameter - so in this case it will look for $form_values['message'].
workflow_ng_token_replace_all(array('message'), $settings, $arguments, $log)
This function does the actual replacements for all variables listed in the first array. It returns an associative array, where the keys are the variable names and the values the variable values, which can be conveniently used with extract().
That's all :)
and conditions...?
Implementing conditions works exactly the same way, except one difference - the return value. Conditions have to return their evaluation result as return value, which will be interpreted as a boolean value.
