Index: uc_file_retro.module
===================================================================
--- uc_file_retro.module	(revision 49)
+++ uc_file_retro.module	(working copy)
@@ -53,7 +53,6 @@
       '#weight' => 9,
     );
 
-    $form['#validate'][] = 'uc_file_retro_form_validate';
     $form['#submit'][] = 'uc_file_retro_form_submit';
     $form['submit']['#weight'] = 10;
     $form['cancel']['#weight'] = 11;
@@ -63,7 +62,7 @@
 /**
  * Submit the feature form, and add to the queue if selected.
  */
-function uc_file_retro_form_submit($form_id, $form_state, $form) {
+function uc_file_retro_form_submit($form, &$form_state) {
 
   if ($form_state['values']['form_id'] == 'uc_file_feature_form') {
 
@@ -82,9 +81,9 @@
 
       db_query("
         INSERT INTO {uc_file_retro_queue} (pfid, fid, model, description, status, created)
-        VALUES (%d, %d, '%s', '%s', 'in_queue', %d)", $form_state['values']['pfid'], $fid, $form_state['values']['uc_file_model'], $form_state['values']['uc_file_description'], time());
+        VALUES (%d, %d, '%s', '%s', 0, %d)", $form_state['values']['pfid'], $fid, $form_state['values']['uc_file_model'], $form_state['values']['uc_file_description'], time());
 
-      if (empty($form_state['values']['uc_file_model'])) $form_state['values']['uc_file_model'] = 'All SKUs';
+      if (empty($form_state['values']['uc_file_model'])) $form_state['values']['uc_file_model'] = t('All SKUs');
 
       drupal_set_message('Queued product feature '.$form_state['values']['pfid'].' for '.$form_state['values']['uc_file_model']);
     }
@@ -108,14 +107,14 @@
   $rows = array();
 
   // Get information for each product in the queue.
-  $query = pager_query("select n.title, n.nid, q.pfid, q.qid, q.description, q.status, uf.filename, q.model, q.created
-    from {uc_file_retro_queue} q
-    left join {uc_files} uf on q.fid = uf.fid
-    inner join {uc_product_features} upf on q.pfid = upf.pfid
-    inner join {node} n on n.nid = upf.nid
-    where q.status = 'in_queue'".
+  $query = pager_query("SELECT n.title, n.nid, q.pfid, q.qid, q.description, q.status, uf.filename, q.model, q.created
+    FROM {uc_file_retro_queue} q
+    LEFT JOIN {uc_files} uf on q.fid = uf.fid
+    INNER JOIN {uc_product_features} upf on q.pfid = upf.pfid
+    INNER JOIN {node} n on n.nid = upf.nid
+    WHERE q.status = 0".
     tablesort_sql($header), 30, 0,
-    "SELECT COUNT(*) FROM {uc_file_retro_queue} where status = 'in_queue'");
+    "SELECT COUNT(*) FROM {uc_file_retro_queue} WHERE status = 0");
 
   if (!$query) {
     $header = array(array('data' => t('Error!')));
@@ -124,8 +123,13 @@
   }
 
   while ($q = db_fetch_object($query)) {
-    empty($q->model) ? $model = 'Any' : $model = $q->model;
-    $ordercount = db_result(db_query("SELECT COUNT(DISTINCT(order_id)) FROM {uc_order_products} WHERE nid = %d AND model = '%s'", $q->nid, $q->model));
+    // Get the models affected by this queue, which may be all models, if the value is empty.
+    if (!empty($q->model)) {
+      $ordercount = db_result(db_query("SELECT COUNT(DISTINCT(order_id)) FROM {uc_order_products} WHERE nid = %d AND model = '%s'", $q->nid, $q->model));
+    }
+    else {
+      $ordercount = db_result(db_query("SELECT COUNT(DISTINCT(order_id)) FROM {uc_order_products} WHERE nid = %d", $q->nid));
+    }
     $rows[] = array(
       array('data' => $q->qid),
       array('data' => $q->title),
@@ -149,7 +153,13 @@
 function uc_file_retro_queue_process($qid) {
   $process = db_fetch_object(db_query('SELECT q.fid, q.pfid, q.model, uf.filename from {uc_file_retro_queue} q LEFT JOIN {uc_files} uf ON uf.fid = q.fid WHERE qid = %d', $qid));
   $feature = db_fetch_object(db_query("SELECT * FROM {uc_product_features} where pfid = %d", $process->pfid));
-  $count = db_result(db_query("select count(*) from {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id WHERE uop.model = '%s'", $process->model));
+  // Get the models affected by this queue, which may be all models, if the value is empty.
+  if (!empty($process->model)) {
+    $count = db_result(db_query("select count(*) from {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id WHERE uop.model = '%s'", $process->model));
+  }
+  else {
+    $count = db_result(db_query("select count(*) from {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id"));
+  }
 
   $batch = array('operations' => array(),
     'finished' => 'uc_file_batch_finished',
@@ -175,12 +185,19 @@
   global $user;
 
   // TODO: Make this a config somewhere.
-  $limit = variable_get('uc_file_retro_batch_limit', 100);
+  $limit = variable_get('uc_file_retro_batch_limit', 1000);
 
   // Find all orders
-  $orders = db_query("SELECT uop.*, uo.*, u.name FROM {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id LEFT JOIN {users} u ON u.uid = uo.uid
-    WHERE uop.nid = %d AND uop.model = '%s' AND uo.order_id > %d ORDER BY uo.order_id LIMIT %d", $nid, $model, $context['sandbox']['current_order'], $limit);
-
+  // Get the models affected by this queue, which may be all models, if the value is empty.
+  // TODO:use a proper pager_query and offset for continuing processes.
+  if (!empty($model)) {
+    $orders = db_query("SELECT uop.*, uo.*, u.name FROM {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id LEFT JOIN {users} u ON u.uid = uo.uid
+      WHERE uop.nid = %d AND uop.model = '%s' AND uo.order_id > %d ORDER BY uo.order_id LIMIT %d", $nid, $model, $context['sandbox']['current_order'], $limit);
+  }
+  else {
+    $orders = db_query("SELECT uop.*, uo.*, u.name FROM {uc_order_products} uop LEFT JOIN {uc_orders} uo ON uop.order_id = uo.order_id LEFT JOIN {users} u ON u.uid = uo.uid
+      WHERE uop.nid = %d AND uo.order_id > %d ORDER BY uo.order_id LIMIT %d", $nid, $context['sandbox']['current_order'], $limit);  
+  }
   // Loop through all users who have bought this product feature and add / renew the files.
   // TODO: Check expiration rules for this file.
   while ($order = db_fetch_object($orders)) {
@@ -193,14 +210,26 @@
     }
 
     // TODO: Check to make sure the user doesn't already have the file.
-    $context['results'][] = array('order_id' => $order->order_id, 'user_id' => $order->uid, 'username' => $order->name, 'purchased' => $order->created);
+    $context['results'][] = array('order_id' => $order->order_id, 'user_id' => $order->uid, 'username' => $order->name, 'purchased' => $order->created, 'qid' => $qid, 'nid' => $nid, 'model' => $model);
     $context['sandbox']['progress']++;
     $context['sandbox']['current_order'] = $order->order_id;
     $context['message'] = 'Currently processing order #'. $order->order_id;
     $account = user_load($order->uid);
 
+    // Get all the features of this product to calculate the file limits.
+    $product_feature = db_fetch_object(db_query("SELECT * FROM {uc_product_features} AS upf
+      INNER JOIN {uc_file_products} AS ufp ON upf.pfid = ufp.pfid
+      INNER JOIN {uc_files} AS uf ON ufp.fid = uf.fid
+      WHERE upf.nid = %d AND ufp.fid = %d", $nid, $fid));
+    // Get the limits from the product feature. (Or global if it says pass through)
+    $file_limits = array(
+      'download_limit' => uc_file_get_download_limit($product_feature),
+      'address_limit'  => uc_file_get_address_limit($product_feature),
+      'expiration'     => _uc_file_expiration_date(uc_file_get_time_limit($product_feature), NULL),
+    );
+
     // Add the file.
-    uc_file_user_renew($fid, $account, $pfid);
+    uc_file_user_renew($fid, $account, $pfid, $file_limits, TRUE);
 
     // Add order comment
     $filename = db_result(db_query("SELECT filename from {uc_files} where fid = %d", $fid));
@@ -223,12 +252,17 @@
       $order_link = l($result['order_id'], 'admin/store/orders/'.$result['order_id']);
       $items[] = t('User !user placed order !order_link on @date',
         array('!user' => l($result['username'], "user/".$result['user_id']), '!order_link' => $order_link, '@date' => format_date($result['purchased'], 'small')));
+      $qid = $result['qid'];
+      $nid = $result['nid'];
+      $model = $result['model'];
     }
+    // TODO: if not finished, queue the remainder.
+    uc_file_retro_update_row($qid, 1);
+
   }
   else {
     $items = array('#type' => 'markup', '#value' => t('Finished with an error.'));
   }
-  //uc_file_retro_update_row($qid, 'processed');
   $_SESSION['uc_file_retro_batch_results'] = $items;
 }
 
@@ -257,7 +291,7 @@
 /**
  * Helper functions
  */
-function uc_file_retro_update_row($qid, $status = 'processed') {
-  if (!$qid) exit;
-  db_query("UPDATE {uc_file_retro_queue} SET status = '%s' WHERE qid = %d LIMIT 1", $status, $qid);
+function uc_file_retro_update_row($qid, $status = 1) {
+  if (!$qid) return;
+  db_query("UPDATE {uc_file_retro_queue} SET status = %d WHERE qid = %d LIMIT 1", $status, $qid);
 }
Index: uc_file_retro.install
===================================================================
--- uc_file_retro.install	(revision 49)
+++ uc_file_retro.install	(working copy)
@@ -56,6 +56,10 @@
         'description' => t('The model / SKU of the product.'),
         'type'        => 'varchar',
         'length'      => 255),
+      'description'           => array(
+        'description' => t('The product description.'),
+        'type'        => 'varchar',
+        'length'      => 255),
       'shippable'           => array(
         'description' => t('Whether the file product is shippable'),
         'type'        => 'int',
@@ -99,3 +103,12 @@
   db_add_index($ret, 'uc_file_retro_queue', 'pfid', array('pfid'));
   return $ret;
 }
+
+/**
+ * Add the missing 'description' field.
+ */
+function uc_file_retro_update_6002() {
+  $ret = array();
+  db_add_field($ret, 'uc_file_retro_queue', 'description', array('type' => 'varchar', 'length' => 255, 'description' => t('The product description.')));
+  return $ret;
+}
