Index: signup_status.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/signup_status/signup_status.admin.inc,v
retrieving revision 1.4
diff -u -p -r1.4 signup_status.admin.inc
--- signup_status.admin.inc	20 Sep 2009 00:27:59 -0000	1.4
+++ signup_status.admin.inc	20 Sep 2009 00:51:33 -0000
@@ -179,17 +179,141 @@ function signup_status_admin_settings_fo
   }
 
   // See if we modified any existing status codes.
-  $signup_status_codes = signup_status_codes();
   if (!empty($values['status'])) {
+    $count_changed_status_codes = array();
+    $signup_status_codes = signup_status_codes();
     foreach ($values['status'] as $cid => $status) {
       $status['cid'] = $cid;
       $diff = array_diff_assoc($status, $signup_status_codes[$cid]);
       if (!empty($diff)) {
+        if (isset($diff['mod_signup_count'])) {
+          $count_changed_status_codes[] = $status;
+        }
         drupal_write_record('signup_status_codes', $status, 'cid');
         drupal_set_message(t('Status code %name has been updated.', array('%name' => $status['name'])));
         watchdog('signup_status', 'Status code %name has been updated.', array('%name' => $status['name']));
       }
     }
+    if (!empty($count_changed_status_codes)) {
+      signup_status_admin_signup_count_change($count_changed_status_codes);
+    }
+  }
+}
+
+/**
+ * Change the mod_signup_count and update signup totals via Batch API.
+ *
+ * @param $status_codes
+ *   Array of signup status definitions (as returned by signup_status_codes())
+ *   that have changed. The 'mod_signup_count' element in each subarray should
+ *   hold the new value to change into.
+ *
+ * @see signup_status_codes()
+ * @see signup_status_admin_signup_count_change_batch()
+ * @see signup_status_admin_signup_count_change_finished()
+ */
+function signup_status_admin_signup_count_change($status_codes) {
+  $title = t('Updating signup totals and checking limits for changes to if the signup status modifies the signup count');
+  $batch = array(
+    'operations' => array(
+      array('signup_status_admin_signup_count_change_batch', array($status_codes)),
+    ),
+    'finished' => 'signup_status_admin_signup_count_change_finished',
+    'title' => $title,
+    'init_message' => $title,
+    'progress_message' => t('Updating signup totals and checking limits...'),
+    'error_message' => t('Error updating signup totals and checking limits.'),
+    'file' => drupal_get_path('module', 'signup_status') . '/signup_status.admin.inc',
+  );
+  batch_set($batch);
+}
+
+/**
+ * Batch worker to check signup totals based on changes mod_signup_count.
+ *
+ * @param $status_codes
+ *   Array of signup status definitions (as returned by signup_status_codes())
+ *   that have changed. The 'mod_signup_count' element in each subarray should
+ *   hold the new value to change into.
+ * @param $context
+ *   Reference to a Batch API context array to track progress of the batch.
+ *
+ * @see signup_status_admin_signup_count_change()
+ * @see signup_status_admin_signup_count_change_finished()
+ */
+function signup_status_admin_signup_count_change_batch($status_codes, &$context) {
+  if (empty($context['sandbox']['nodes'])) {
+    // Initialize the work to do -- remember all the nodes that have signups
+    // in any effected status, since we need to modify the totals and check
+    // limits.
+    $status_cids = array();
+    foreach ($status_codes as $code) {
+      $status_cids[] = $code['cid'];
+    }
+    $placeholders = db_placeholders($status_cids);
+    $query = db_query("SELECT nid FROM {signup_log} WHERE status IN ($placeholders) GROUP BY nid", $status_cids);
+    while ($nid = db_result($query)) {
+      $context['sandbox']['nodes'][] = $nid;
+    }
+    $context['finished'] = 0;
+    $context['sandbox']['max'] = count($context['sandbox']['nodes']);
+    $context['sandbox']['progress'] = 0;
+    $context['message'] = t('Checking signup count and limits...');
+    $context['results']['updated'] = 0;
+    $context['results']['processed'] = 0;
+    $context['results']['status_codes'] = $status_codes;
+
+    // In case of a race condition, ensure there's something to process.
+    if (empty($context['sandbox']['max'])) {
+      $context['finished'] = 1;
+      return;
+    }
+  }
+
+  // If there's work to do, process a node.
+  if (!empty($context['sandbox']['nodes'])) {
+    $nid = array_pop($context['sandbox']['nodes']);
+    // First update the signups for all affected status codes.
+    foreach ($status_codes as $status) {
+      db_query("UPDATE {signup_log} SET count_towards_limit = %d WHERE nid = %d AND status = %d", $status['mod_signup_count'], $nid, $status['cid']);
+    }
+    // Now, load the node, which will count and sum the effective signups.
+    $node = node_load($nid);
+    // Finally, check the limit now that the total has potentially changed.
+    _signup_check_limit($node, 'total');
+    $context['results']['updated']++;
+    $context['message'] = t('Processed signups for %title', array('%title' => $node->title));
+  }
+  $context['sandbox']['progress']++;
+  $context['results']['processed']++;
+  $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
+}
+
+/**
+ * Batch API callback once all signup totals have been modified.
+ *
+ * @see signup_status_admin_signup_count_change()
+ * @see signup_status_admin_signup_count_change_batch()
+ */
+function signup_status_admin_signup_count_change_finished($success, $results, $operations) {
+  if ($success) {
+    if (!empty($results)) {
+      drupal_set_message(format_plural($results['updated'], 'Updated signup totals on one node based on changes to signup counts.', 'Updated signup totals on @count nodes based on changes to signup counts.'));
+      foreach ($results['status_codes'] as $status) {
+        if ($status['mod_signup_count']) {
+          drupal_set_message(t('Signup status %name now modifies the signup count.', array('%name' => $status['name'])));
+        }
+        else {
+          drupal_set_message(t('Signup status %name now does not modify the signup count.', array('%name' => $status['name'])));
+        }
+      }
+    }
+  }
+  else {
+    // An error occurred.
+    // $operations contains the operations that remained unprocessed.
+    $error_operation = reset($operations);
+    drupal_set_message(t('An error occurred while processing with arguments: @error', array('@error' => var_export($error_operation[0], TRUE))), 'error');
   }
 }
 
