Index: activity.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/activity/Attic/activity.admin.inc,v
retrieving revision 1.1.2.40
diff -u -p -r1.1.2.40 activity.admin.inc
--- activity.admin.inc	12 Apr 2010 16:36:56 -0000	1.1.2.40
+++ activity.admin.inc	16 May 2010 17:59:32 -0000
@@ -132,8 +132,10 @@ function activity_form_submit($form, &$f
       $params['everyone-pattern-' . $id] = $values['messages']['everyone-pattern-' . $id];
     }
     $desc = $values['messages']['description'];
+    $update = TRUE;
     if (!$aid = $values['messages']['aid']) {
       $aid = NULL;
+      $update = FALSE;
     }
     
     // handle the types, thanks Checkboxes :-D
@@ -146,6 +148,13 @@ function activity_form_submit($form, &$f
     
     // Save the action
     include_once('includes/actions.inc');
+    // In order to save the aid into the actions.parameters column, when a new
+    // template is created, the aid must be generated. Can look into using
+    // {actions_aid} table for this as well. SELECT aid + 1 ORDER BY aid DESC ?
+    if (!$update) {
+      $aid = actions_save('activity_record', 'activity', $params, $desc);
+    }
+    $params['aid'] = $aid;
     $aid = actions_save('activity_record', 'activity', $params, $desc, $aid);
 
     // Save the trigger assignment
@@ -649,4 +658,122 @@ function activity_access_rebuild_process
     // If finished, delete the sandbox.
     unset($context['sandbox']);
   } 
+}
+
+/**
+ * Set a batch process to regenerate activity for a specific hook and op pair.
+ *
+ * @param $aid
+ *  The actions.aid for this template.
+ *
+ * @return none
+ */
+function activity_batch_regenerate($aid) {
+  $trigger_assignment = db_fetch_object(db_query("SELECT hook, op FROM {trigger_assignments} WHERE aid = '%s'", $aid));
+  if (!empty($trigger_assignment)) {
+    $batch = array(
+      'title' => t('Regenerating @description Activity', array('@description' => db_result(db_query("SELECT description from {actions} WHERE aid = '%s'", $aid)))),
+      'operations' => array(
+        array('activity_batch_delete', array($aid)),
+        array('activity_batch_regenerate_step', array($aid, $trigger_assignment->hook, $trigger_assignment->op)),
+      ),
+      'file' => drupal_get_path('module', 'activity') . '/activity.admin.inc',
+    );
+
+    batch_set($batch);
+    batch_process('admin/build/activity');
+  }
+}
+
+/**
+ * Batch deletion step.
+ *
+ * @param $aid
+ *  The actions.aid for this template.
+ * @param $batch_context
+ *  The context array for this batch operation.
+ */
+function activity_batch_delete($aid, &$batch_context) {
+  if (!isset($batch_context['sandbox']['last_activity_id'])) {
+    $batch_context['sandbox']['last_activity_id'] = 0;
+    $batch_context['sandbox']['progress'] = 0;
+    $batch_context['sandbox']['max'] = db_result(db_query("SELECT COUNT(aid) FROM {activity} WHERE actions_id = '%s'", $aid));
+  }
+  $limit = 200;
+  $activity_to_be_deleted = db_query_range("SELECT aid FROM {activity} WHERE aid > %d AND actions_id = '%s' ORDER BY aid ASC", $batch_context['sandbox']['last_activity_id'], $aid, 0, $limit);
+  $activity_ids = array();
+  while ($row = db_fetch_object($activity_to_be_deleted)) {
+    $activity_ids[] = $row->aid;
+    $batch_context['sandbox']['last_activity_id'] = $row->aid;
+    $batch_context['sandbox']['progress']++;
+  }
+
+  activity_delete($activity_ids);
+  // Check if not finished.
+  if ($batch_context['sandbox']['progress'] < $batch_context['sandbox']['max']) {
+    $batch_context['finished'] = $batch_context['sandbox']['progress'] / $batch_context['sandbox']['max'];
+  }
+  else {
+    // If finished, delete the sandbox.
+    unset($batch_context['sandbox']);
+  }
+  
+}
+
+/**
+ * Batch regeneration step.
+ *
+ * @param $aid
+ *  The actions.aid for this template.
+ * @param $hook
+ *  The name of the hook being recorded.
+ * @param $op
+ *  The op for the hook being recorded.
+ * @param $batch_context
+ *  An array representing the context for the batch operation.
+ */
+function activity_batch_regenerate_step($aid, $hook, $op, &$batch_context) {
+  $module = activity_module_name($hook);
+  $info  = activity_get_module_info($module);
+  $load_callback = $info->context_load_callback;
+  $limit = 50;
+
+  // Set up the sandbox for the regeneration.
+  if (!isset($batch_context['sandbox']['list'])) {
+    $list_callback = $info->list_callback;
+    $batch_context['sandbox']['list'] = $list_callback($hook, $op);
+    $batch_context['sandbox']['max'] = count($batch_context['sandbox']['list']);
+    $batch_context['sandbox']['progress'] = 0;
+
+    $parameters = db_result(db_query("SELECT a.parameters FROM {actions} a WHERE aid = '%s'", $aid));
+    $batch_context['sandbox']['parameters'] = unserialize($parameters);
+  }
+
+  $count = 0;
+  foreach ($batch_context['sandbox']['list'] as $key => $event) {
+    $context = array();
+    if (++$count > $limit) {
+      break;
+    }
+    else {
+      $context = $load_callback($hook, $op, $event['id']);
+      if (!empty($context)) {
+        $context += array(
+          'created' => $event['created'],
+          'actor' => $event['actor'],
+        );
+        activity_record(NULL, $context + $batch_context['sandbox']['parameters']);
+      }
+      $batch_context['sandbox']['progress']++;
+    }
+    unset($batch_context['sandbox']['list'][$key]);
+  }
+  // Check if not finished.
+  if ($batch_context['sandbox']['progress'] < $batch_context['sandbox']['max']) {
+    $batch_context['finished'] = $batch_context['sandbox']['progress'] / $batch_context['sandbox']['max'];
+  }
+  else {
+    // If finished, delete the sandbox.
+    unset($batch_context['sandbox']);
+  }
 }
\ No newline at end of file
Index: activity.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/activity/activity.install,v
retrieving revision 1.1.2.1.2.6.2.4.2.15
diff -u -p -r1.1.2.1.2.6.2.4.2.15 activity.install
--- activity.install	16 May 2010 04:03:23 -0000	1.1.2.1.2.6.2.4.2.15
+++ activity.install	16 May 2010 17:59:32 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: activity.install,v 1.1.2.1.2.6.2.4.2.15 2010/05/16 04:03:23 scottreynolds Exp $
+// $Id: activity.install,v 1.1.2.1.2.6.2.4.2.14 2010/04/26 16:31:52 scottreynolds Exp $
 
 function activity_install() {
   drupal_install_schema('activity');
@@ -55,12 +55,20 @@ function activity_schema() {
         'not null' => TRUE,
         'unsigned' => TRUE,
       ),
+      'actions_id' => array(
+        'description' => 'Foreign key to the actions table.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '0',
+      ),
     ),
     'primary key' => array('aid'),
     'indexes' => array(
       'nid' => array('nid'),
       'eid' => array('eid'),
-      'created' => array('created'),
+      'created' => array('created'), // Probably not at all useful.
+      'actions_id' => array('actions_id'),
     ),
   );
   
@@ -212,4 +220,23 @@ function activity_update_6201() {
   $ret = array();
   db_change_field($ret, 'activity_messages', 'amid', 'amid', array('type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE));
   return $ret;
+}
+
+/**
+ * Update {activity} table to have the actions_id field.
+ * @see: http://drupal.org/node/463854
+ */
+function activity_update_6202() {
+  $ret = array();
+
+  db_add_field($ret, 'activity', 'actions_id', array(
+        'description' => 'Foreign key to the actions table.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '0',
+      ),
+    array('indexes' => array('actions_id' => array('actions_id'))));
+
+  return $ret;
 }
\ No newline at end of file
Index: activity.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/activity/activity.module,v
retrieving revision 1.1.2.2.2.30.2.31.2.90
diff -u -p -r1.1.2.2.2.30.2.31.2.90 activity.module
--- activity.module	15 May 2010 23:59:20 -0000	1.1.2.2.2.30.2.31.2.90
+++ activity.module	16 May 2010 17:59:33 -0000
@@ -102,6 +102,9 @@ function node_activity_info() {
   foreach (node_get_types() as $type) {
     $info->type_options[$type->type] = t($type->name);
   }
+
+  $info->list_callback = 'node_list_activity_actions';
+  $info->context_load_callback = 'node_load_activity_context';
   return $info;
 }
 
@@ -224,6 +227,14 @@ function activity_menu() {
     'file' => 'activity.admin.inc',
     'type' => MENU_CALLBACK,
   );
+  $items['admin/build/activity/batch/%'] = array(
+    'title' => 'Batch Update',
+    'page callback' => 'activity_batch_regenerate',
+    'page arguments' => array(4, 5),
+    'access arguments' => array('administer activity'),
+    'file' => 'activity.admin.inc',
+    'type' => MENU_CALLBACK,
+  );
   return $items;
 }
 
@@ -398,11 +409,11 @@ function activity_token_values($type, $o
  * activity_get_module_info()
  */
 function activity_record_check($object, $context, $token_objects, $activity_object) {
-  global $user;
+  $account = user_load($context['actor']);
 
   // First check to see if the user opts out.
   $aid = db_result(db_query("SELECT aid FROM {trigger_assignments} WHERE hook = '%s' AND op = '%s'", $context['hook'], $context['op']));
-  if (isset($user->activity_ignore[$aid]) && $user->activity_ignore[$aid] == 0) {
+  if (isset($account->activity_ignore[$aid]) && $account->activity_ignore[$aid] == 0) {
     // user has opted out of this particular action
     return FALSE;
   }
@@ -429,7 +440,10 @@ function activity_record_check($object, 
  *  holds the messages
  */
 function activity_record($object, $context) {
-  global $user;
+  $context += array(
+    'actor' => $GLOBALS['user']->uid,
+    'created' => time(),
+  );
   // find what the type is so we can do the tokenizing
   $activity_object = FALSE;
   foreach (activity_get_module_info() as $module => $info) {
@@ -463,9 +477,8 @@ function activity_record($object, $conte
     $objects[$type] = drupal_clone($context[$type]);
   }
 
-  // @TODO: when doing a bulk update this will break.
-  if (!empty($user->uid) && $user->uid != $objects[$type]->uid) {
-    $objects[$type]->uid = $user->uid;
+  if (!empty($context['actor']) && $context['actor'] != $objects[$type]->uid) {
+    $objects[$type]->uid = $context['actor'];
   }
   
   drupal_alter('activity_objects', $objects, $type);
@@ -520,11 +533,12 @@ function activity_record($object, $conte
   }
 
   $record = new stdClass();
-  $record->uid = (!empty($objects[$type]->uid)) ? $objects[$type]->uid : $user->uid;
+  $record->uid = $context['actor'];
   $record->op = $context['op'];
   $record->type = $activity_object->name;
   $record->nid = $nid;
-  $record->created = time(); // for PHP4 compat. for D7 use REQUEST_TIME
+  $record->created = $context['created'];
+  $record->actions_id = $context['aid'];
   
   // handle the entity id
   if (!empty($info->eid_field) && isset($context[$type]->{$info->eid_field})) {
@@ -794,7 +808,8 @@ function theme_activity_settings_actions
       drupal_ucfirst(str_replace('_', ' ', $result['hook'])),
       $result['description'],
       l('configure', 'admin/build/activity/configure/'. $result['aid']) .' | '.
-      l('delete', 'admin/build/activity/delete/'. $result['aid']),
+      l('delete', 'admin/build/activity/delete/'. $result['aid']) . ' | ' .
+      l('regenerate', 'admin/build/activity/batch/'. $result['aid']),
     );
   }
   $output = theme('table', $header, $rows);
Index: modules/node.activity.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/activity/modules/Attic/node.activity.inc,v
retrieving revision 1.1.2.20
diff -u -p -r1.1.2.20 node.activity.inc
--- modules/node.activity.inc	15 May 2010 22:29:17 -0000	1.1.2.20
+++ modules/node.activity.inc	16 May 2010 17:59:33 -0000
@@ -79,3 +79,61 @@ function node_activity_objects_alter(&$t
     $token_objects['user'] = $GLOBALS['user'];
   }
 }
+
+/**
+ * List all the Activity Actions that match the hook and op.
+ *
+ * @param string $hook
+ *  The hook that is to be fired.
+ * @param string $op
+ *  The op to be used in the hook.
+ *
+ * @return array
+ *  An array keyed by id => timestamp
+ */
+function node_list_activity_actions($hook, $op) {
+  $actions = array();
+  if ($op == 'insert' ) {
+    $sql = "SELECT nid as id, created as created, uid as actor FROM {node}";
+  }
+  elseif ($op == 'view') {
+    $sql = "SELECT nid as id, timestamp as created, uid as actor FROM {history}";
+  }
+
+  if (isset($sql)) {
+    $result = db_query($sql);
+    while ($row = db_fetch_array($result)) {
+      $actions[] = $row;
+    }
+  }
+
+  return $actions;
+}
+
+/**
+ * Load up the context array to pass to activity_record.
+ *
+ * @param string $hook
+ *  The hook that is being fired.
+ * @param string $op
+ *  The op for that hook.
+ * @param string $id
+ *  The id for the action.
+ *
+ * @return array
+ *   The context array for activity_record.
+ * @see trigger_nodeapi
+ */
+function node_load_activity_context($hook, $op, $id) {
+  $node = node_load($id);
+  $context = array();
+  if (!empty($node)) {
+    $context = array(
+      'hook' => $hook,
+      'op' => $op,
+      'node' => $node,
+    );
+  }
+
+  return $context;
+}
\ No newline at end of file
