Index: token_actions.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/token/token_actions.module,v
retrieving revision 1.4.2.9
diff -u -p -r1.4.2.9 token_actions.module
--- token_actions.module	25 Mar 2010 17:49:43 -0000	1.4.2.9
+++ token_actions.module	17 Nov 2010 22:26:46 -0000
@@ -13,7 +13,7 @@
  */
 
 /**
- * Implementation of hook_action_info().
+ * Implements hook_action_info().
  */
 function token_actions_action_info() {
   return array(
@@ -53,24 +53,47 @@ function token_actions_action_info() {
 }
 
 /**
- * Return a form definition so the Send email action can be configured.
+ * Implements hook_mail().
+ */
+function token_actions_mail($key, &$message, $params) {
+  $message['subject'] = $params['subject'];
+  $message['body'][] = $params['body'];
+}
+
+/**
+ * Action callback to send a tokenized e-mail.
  *
- * @param $context
- *   Default values (if we are editing an existing action instance).
- * @return
- *   Form definition.
+ * @see token_actions_send_email_action_form()
+ * @see token_actions_send_email_action_submit()
  */
-function token_actions_send_email_action_form($context) {
-  // Set default values for form.
-  if (!isset($context['recipient'])) {
-    $context['recipient'] = '';
-  }
-  if (!isset($context['subject'])) {
-    $context['subject'] = '';
+function token_actions_send_email_action($object, $context) {
+  token_normalize_context($context);
+  $params['from'] = variable_get('site_mail', ini_get('sendmail_from'));
+  $recipient = token_replace_multiple($context['recipient'], $context);
+  $params['subject'] = str_replace(array("\r", "\n"), '', token_replace_multiple($context['subject'], $context));
+  $params['body'] = token_replace_multiple($context['message'], $context);
+
+  if (drupal_mail('token_actions', 'action_send_email', $recipient, language_default(), $params)) {
+    watchdog('action', 'Sent email to %recipient', array('%recipient' => $recipient));
   }
-  if (!isset($context['message'])) {
-    $context['message'] = '';
+  else {
+    watchdog('error', 'Unable to send email to %recipient', array('%recipient' => $recipient));
   }
+}
+
+/**
+ * Form builder; Prepare a form for a tokenized e-mail action.
+ *
+ * @see token_actions_send_email_action()
+ * @see token_actions_send_email_action_submit()
+ */
+function token_actions_send_email_action_form($context) {
+  // Set default values for form.
+  $context += array(
+    'recipient' => '',
+    'subject' => '',
+    'message' => '',
+  );
 
   $form['recipient'] = array(
     '#type' => 'textfield',
@@ -79,6 +102,8 @@ function token_actions_send_email_action
     '#size' => '20',
     '#maxlength' => '254',
     '#description' => t('The email address to which the message should be sent.'),
+    '#element_validate' => array('token_element_validate'),
+    '#token_types' => array('all'),
   );
   $form['subject'] = array(
     '#type' => 'textfield',
@@ -87,6 +112,8 @@ function token_actions_send_email_action
     '#size' => '20',
     '#maxlength' => '254',
     '#description' => t('The subject of the message.'),
+    '#element_validate' => array('token_element_validate'),
+    '#token_types' => array('all'),
   );
   $form['message'] = array(
     '#type' => 'textarea',
@@ -95,6 +122,8 @@ function token_actions_send_email_action
     '#cols' => '80',
     '#rows' => '20',
     '#description' => t('The message that should be sent.'),
+    '#element_validate' => array('token_element_validate'),
+    '#token_types' => array('all'),
   );
 
   $form['help'] = array(
@@ -104,57 +133,57 @@ function token_actions_send_email_action
     '#title' => t('Placeholder tokens'),
     '#description' => t("The following placeholder tokens can be used in to generate the URL path. Some tokens may not be available, depending on the context in which the action is triggered."),
   );
-
   $form['help']['tokens'] = array(
-    '#value' => theme('token_help', 'all'),
+    '#value' => theme('token_tree', 'all'),
   );
 
   return $form;
 }
 
-function token_actions_send_email_action_submit($form, &$form_state) {
-  // Process the HTML form to store configuration. The keyed array that
-  // we return will be serialized to the database.
-  $params = array(
+/**
+ * Process token_actions_send_email_action_form form submissions.
+ *
+ * @see token_actions_send_email_action()
+ * @see token_actions_send_email_action_form()
+ */
+function token_actions_send_email_action_submit($form, $form_state) {
+  return array(
     'recipient' => $form_state['values']['recipient'],
     'subject'   => $form_state['values']['subject'],
     'message'   => $form_state['values']['message'],
   );
-  return $params;
 }
 
 /**
- * Implementation of a configurable Drupal action.
- * Sends an email.
+ * Action callback to send a message to the current user's screen.
+ *
+ * @see token_actions_message_action_form()
+ * @see token_actions_message_action_submit()
  */
-function token_actions_send_email_action($object, $context) {
+function token_actions_message_action(&$object, $context = array()) {
   token_normalize_context($context);
-  $params['from'] = variable_get('site_mail', ini_get('sendmail_from'));
-  $recipient = token_replace_multiple($context['recipient'], $context);
-  $params['subject'] = str_replace(array("\r", "\n"), '', token_replace_multiple($context['subject'], $context));
-  $params['body'] = token_replace_multiple($context['message'], $context);
-
-  if (drupal_mail('token_actions', 'action_send_email', $recipient, language_default(), $params)) {
-    watchdog('action', 'Sent email to %recipient', array('%recipient' => $recipient));
-  }
-  else {
-    watchdog('error', 'Unable to send email to %recipient', array('%recipient' => $recipient));
-  }
-}
-
-function token_actions_mail($key, &$message, $params) {
-  $message['subject'] = $params['subject'];
-  $message['body'][] = $params['body'];
+  $context['message'] = token_replace_multiple($context['message'], $context);
+  drupal_set_message($context['message']);
 }
 
+/**
+ * Form builder; Prepare a form for a tokenized message action.
+ *
+ * @see token_actions_message_action()
+ * @see token_actions_message_action_submit()
+ */
 function token_actions_message_action_form($context) {
+  $context += array('message' => '');
+
   $form['message'] = array(
     '#type' => 'textarea',
     '#title' => t('Message'),
-    '#default_value' => isset($context['message']) ? $context['message'] : '',
+    '#default_value' => $context['message'],
     '#required' => TRUE,
     '#rows' => '8',
     '#description' => t('The message to be displayed to the current user.'),
+    '#element_validate' => array('token_element_validate'),
+    '#token_types' => array('all'),
   );
 
   $form['help'] = array(
@@ -164,40 +193,53 @@ function token_actions_message_action_fo
     '#title' => t('Placeholder tokens'),
     '#description' => t("The following placeholder tokens can be used in the custom message text. Some tokens may not be available, depending on the context in which the action is triggered."),
   );
-
   $form['help']['tokens'] = array(
-    '#value' => theme('token_help', 'all'),
+    '#value' => theme('token_tree', 'all'),
   );
 
   return $form;
 }
 
-function token_actions_message_action_submit($form, &$form_state) {
+/**
+ * Process token_actions_message_action_form form submissions.
+ *
+ * @see token_actions_message_action()
+ * @see token_actions_message_action_form()
+ */
+function token_actions_message_action_submit($form, $form_state) {
   return array('message' => $form_state['values']['message']);
 }
 
 /**
- * Implementation of a configurable Drupal action.
- * Sends a configurable message to the current user's screen.
+ * Action callback to redirect the user to a tokenized URL.
+ *
+ * @see token_actions_goto_action_form()
+ * @see token_actions_goto_action_submit()
  */
-function token_actions_message_action(&$object, $context = array()) {
+function token_actions_goto_action($object, $context) {
   token_normalize_context($context);
-  $context['message'] = token_replace_multiple($context['message'], $context);
-  drupal_set_message($context['message']);
+  drupal_goto(token_replace_multiple($context['url'], $context));
 }
 
 /**
- * Implementation of a configurable Drupal action.
- * Redirect user to a URL.
+ * Form builder; Prepare a form for a tokenized redirect action.
+ *
+ * @see token_actions_goto_action()
+ * @see token_actions_goto_action_submit()
  */
 function token_actions_goto_action_form($context) {
+  $context += array('url' => '');
+
   $form['url'] = array(
     '#type' => 'textfield',
     '#title' => t('URL'),
     '#description' => t('The URL to which the user should be redirected. This can be an internal URL like node/1234 or an external URL like http://drupal.org.'),
-    '#default_value' => isset($context['url']) ? $context['url'] : '',
+    '#default_value' => $context['url'],
     '#required' => TRUE,
+    '#element_validate' => array('token_element_validate'),
+    '#token_types' => array('all'),
   );
+
   $form['help'] = array(
     '#type' => 'fieldset',
     '#collapsible' => TRUE,
@@ -205,35 +247,36 @@ function token_actions_goto_action_form(
     '#title' => t('Placeholder tokens'),
     '#description' => t("The following placeholder tokens can be used in the URL path. Some tokens may not be available, depending on the context in which the action is triggered."),
   );
-
   $form['help']['tokens'] = array(
-    '#value' => theme('token_help', 'all'),
+    '#value' => theme('token_tree', 'all'),
   );
 
   return $form;
 }
 
-function token_actions_goto_action_submit($form, &$form_state) {
-  return array(
-    'url' => $form_state['values']['url']
-  );
-}
-
-function token_actions_goto_action($object, $context) {
-  token_normalize_context($context);
-  drupal_goto(token_replace_multiple($context['url'], $context));
+/**
+ * Process token_actions_goto_action_form form submissions.
+ *
+ * @see token_actions_goto_action()
+ * @see token_actions_goto_action_form()
+ */
+function token_actions_goto_action_submit($form, $form_state) {
+  return array('url' => $form_state['values']['url']);
 }
 
 /**
- * Load, into the context, the common objects user and node so we can use their
- * tokens. Sometimes Trigger, or Actions, load them for us, but sometimes not.
+ * Normalize an action context for use with token_replace_multiple().
  */
 function token_normalize_context(&$context) {
   $context['global'] = NULL;
+
   if (empty($context['user']) && !empty($context['node'])) {
     $context['user'] = user_load(array('uid' => $context['node']->uid));
   }
   if (empty($context['node']) && !empty($context['comment']) && !empty($context['comment']->nid)) {
     $context['node'] = node_load($context['comment']->nid);
   }
+  if (empty($context['user']) && !empty($context['account'])) {
+    $context['user'] = $context['account'];
+  }
 }
Index: token.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/token/token.test,v
retrieving revision 1.1.2.17
diff -u -p -r1.1.2.17 token.test
--- token.test	11 Nov 2010 00:12:18 -0000	1.1.2.17
+++ token.test	17 Nov 2010 22:26:46 -0000
@@ -3,7 +3,7 @@
 
 /**
  * @file
- * Tests for the token and token_actions modules.
+ * Tests for the token module.
  */
 
 /**
@@ -345,69 +345,3 @@ class TokenMenuTestCase extends TokenTes
     $this->assertTokens('node', $node, $tokens);
   }
 }
-
-class TokenTestCase extends DrupalWebTestCase {
-  public static function getInfo() {
-    return array(
-      'name' => t('Token and token action tests'),
-      'description' => t('Test some of the token actions and tokens.'),
-      'group' => t('Token'),
-    );
-  }
-
-  function setUp() {
-    parent::setUp('token', 'token_actions', 'trigger');
-  }
-
-  /**
-   * Test various behaviors for anonymous users.
-   */
-  function testTokenActionsFunctionalTest() {
-    // Create a user with permission to view the actions administration pages.
-    $user = $this->drupalCreateUser(array('administer actions', 'administer site configuration', 'administer users'));
-    $this->drupalLogin($user);
-
-    // Set the site name to something more exciting than Drupal / simpletest@example.com.
-    $settings = array();
-    $site_name = $this->randomName();
-    $site_mail = $this->randomName() .'@example.com';
-    $settings['site_name'] = $site_name;
-    $settings['site_mail'] = $site_mail;
-
-    $this->drupalPost('admin/settings/site-information', $settings, t('Save configuration'));
-    $this->assertText('saved', 'Site settings saved.');
-
-    // Create an action to display to users
-    $action = array();
-    $action['action'] = md5('token_actions_message_action');
-    $this->drupalPost('admin/settings/actions', $action, t('Create'));
-
-    // Configure the action to use a handful of tokens.
-    $action = array();
-    $action_description = $this->randomName();
-    $action['actions_description'] = $action_description;
-    $action['message'] = 'Hello simpletest | [user-name] | [user-id] | [user-mail] | [site-name] | [site-mail]';
-    $this->drupalPost('admin/settings/actions/configure/'. md5('token_actions_message_action'), $action, t('Save'));
-
-    // Trigger the action when a user is created.
-    $trigger = array();
-    $trigger['aid'] = md5('1'); //TODO don't hardcode the 1.
-    // TODO this should be assigned to a specific aid like aid_4, but that's not possible b/c actions creates non-unique form names.
-    // so instead we use "aid" which is the "after a user is created" trigger.
-    $this->drupalPost('admin/build/trigger/user', $trigger, t('Assign'));
-    // TODOXXX confirm each post gets saved.
-
-    // Create a user to trigger the action.
-    $edit = array();
-    $edit['name']   = $this->randomName();
-    $edit['mail']   = $edit['name'] .'@example.com';
-    $pass = user_password();
-    $edit['pass[pass1]']   = $pass;
-    $edit['pass[pass2]']   = $pass;
-
-    $this->drupalPost('admin/user/user/create', $edit, t('Create new account'));
-    $this->assertText('Hello simpletest | '. $user->name  .' | '. $user->uid .' | '. $user->mail .' | '. $site_name .' | '. $site_mail, 'Tokenized message displays');
-
-  }
-
-}
Index: token_actions.test
===================================================================
RCS file: token_actions.test
diff -N token_actions.test
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ token_actions.test	17 Nov 2010 22:26:46 -0000
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Tests for the token_actions module.
+ */
+
+class TokenActionsTestCase extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => t('Token action tests'),
+      'description' => t('Test some of the token actions and tokens.'),
+      'group' => t('Token'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('token', 'token_actions', 'trigger');
+    $user = $this->drupalCreateUser(array('administer actions', 'administer site configuration', 'administer users'));
+    $this->drupalLogin($user);
+  }
+
+  /**
+   * Test user actions and triggers.
+   */
+  function testUserActions() {
+    $insert_action = $this->createAction('token_actions_message_action', array(
+      'message' => 'Yay [site-name] has a new user [user] with an ID of [uid] and e-mail address of [mail]!',
+    ));
+    $this->assignTriggerAction('user', 'insert', $insert_action);
+
+    // Create a user to trigger the action.
+    $edit = array();
+    $edit['name'] = $this->randomName();
+    $edit['mail'] = $edit['name'] .'@example.com';
+    $edit['pass[pass1]'] = $this->randomName();
+    $edit['pass[pass2]'] = $edit['pass[pass1]'];
+
+    $this->drupalPost('admin/user/user/create', $edit, t('Create new account'));
+    $account = user_load(array('name' => $edit['name']));
+    $this->assertText("Yay Drupal has a new user {$account->name} with an ID of {$account->uid} and e-mail address of {$account->mail}!", 'Tokenized message displays');
+  }
+
+  /**
+   * Create an action.
+   *
+   * @param $action
+   *   The machine name of the action.
+   * @param $edit
+   *   An optional array to pass onto drupalPost() for configuring the action.
+   *
+   * @return
+   *   The created action object.
+   */
+  function createAction($action, $edit = array()) {
+    $edit += array(
+      'actions_description' =>  $this->randomName(),
+    );
+    $this->drupalPost('admin/settings/actions/configure/'. md5($action), $edit, t('Save'));
+    $this->assertText('The action has been successfully saved.');
+    return db_fetch_object(db_query("SELECT * FROM {actions} WHERE type = 'system' AND callback = '%s' AND description = '%s'", $action, $edit['actions_description']));
+  }
+
+  /**
+   * Assign an action to a trigger.
+   *
+   * @param $type
+   *   The trigger type.
+   * @param $trigger
+   *   The trigger.
+   * @param $action
+   *   The action object.
+   */
+  function assignTriggerAction($type, $trigger, $action) {
+    $edit['aid'] = md5($action->aid);
+    $this->drupalPost("admin/build/trigger/{$type}", $edit, 'Assign', array(), array(), "trigger-{$type}-{$trigger}-assign-form");
+    return $this->assertLinkByHref("admin/build/trigger/unassign/{$type}/{$trigger}/{$edit['aid']}", 0, t('Action assigned to @type @trigger trigger.', array('@type' => $type, '@trigger' => $trigger)));
+  }
+}
Index: token.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/token/token.module,v
retrieving revision 1.7.4.43
diff -u -p -r1.7.4.43 token.module
--- token.module	1 Nov 2010 03:51:41 -0000	1.7.4.43
+++ token.module	17 Nov 2010 22:26:46 -0000
@@ -544,7 +544,9 @@ function token_get_date_token_values($ti
  */
 function token_get_invalid_tokens_by_context($value, $valid_types = array(), $leading = TOKEN_PREFIX, $trailing = TOKEN_SUFFIX) {
   // Add the token types that are always valid in global context.
-  $valid_types[] = 'global';
+  if (!in_array('all', $valid_types)) {
+    $valid_types[] = 'global';
+  }
 
   $invalid_tokens = array();
   $valid_tokens = token_get_list($valid_types);
