Index: project.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/project.module,v
retrieving revision 1.308
diff -u -p -r1.308 project.module
--- project.module	9 Feb 2008 00:26:36 -0000	1.308
+++ project.module	6 Mar 2008 03:54:23 -0000
@@ -682,7 +682,6 @@ function project_page_overview($termname
           $where = 'tr.tid IN ('. implode(',', $placeholders) .')';
           $release_settings['wheres'][] = $where;
 
-          $release_settings['fields'][] = 'prp.snapshot_table';
           // We need to grab the uid and type for the project node, so
           // that node_access() will work properly without a full
           // node_load() when we're generating the download table in
@@ -791,8 +790,7 @@ function project_page_overview($termname
       }
     }
     else {
-      $release_type = $project->snapshot_table ? 'all' : 'official';
-      $project->download_table = theme('project_release_table_overview', $project, 'recommended', $release_type, t('Version'), FALSE);
+      $project->download_table = theme('project_release_table_overview', $project, 'recommended', 'all', t('Version'), FALSE);
     }
 
     $project->links['project_more_info'] = array(
Index: release/project_release.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project_release.css,v
retrieving revision 1.5
diff -u -p -r1.5 project_release.css
--- release/project_release.css	14 Jan 2007 03:06:19 -0000	1.5
+++ release/project_release.css	6 Mar 2008 03:54:23 -0000
@@ -23,7 +23,7 @@ table.releases {
 }
 
 table.releases .release-title {
-  width: 30%;
+  width: 28%;
 }
 
 table.releases .release-date {
@@ -31,9 +31,13 @@ table.releases .release-date {
 }
 
 table.releases .release-size {
-  width: 15%;
+  width: 10%;
 }
 
 table.releases .release-links {
-  width: 40%;
+  width: 25%;
+}
+
+table.releases .release-status {
+  width: 22%;
 }
Index: release/project_release.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project/release/project_release.module,v
retrieving revision 1.62
diff -u -p -r1.62 project_release.module
--- release/project_release.module	5 Mar 2008 19:23:24 -0000	1.62
+++ release/project_release.module	6 Mar 2008 03:54:33 -0000
@@ -1451,6 +1451,10 @@ function project_release_project_nodeapi
       foreach ($fields as $field) {
         $node->$field = $project->$field;
       }
+      $wants_snapshots = db_result(db_query('SELECT tid FROM {project_release_supported_versions} WHERE nid = %d AND snapshot = 1 LIMIT 1', $node->nid));
+      if (!empty($wants_snapshots)) {
+        $node->project_release_show_snapshots = TRUE;
+      }
       break;
 
     case 'insert':
@@ -1571,9 +1575,9 @@ function theme_project_release_project_d
     return;
   }
   $output = '<h3>'. t('Releases') .'</h3>';
-  $output .= project_release_table($node, 'recommended', 'official', t('Official releases'));
-  if ($node->snapshot_table) {
-    $output .= project_release_table($node, 'recommended', 'snapshot', t('Development snapshots'));
+  $output .= project_release_table($node, 'supported', 'official', t('Official releases'));
+  if ($node->project_release_show_snapshots) {
+    $output .= project_release_table($node, 'supported', 'snapshot', t('Development snapshots'));
   }
   return $output;
 }
@@ -1623,6 +1627,7 @@ function theme_project_release_table_ove
  * @param $table_type
  *   Indicates what kind of table should be generated. Possible options:
  *    'recommended': Only show the current recommended versions.
+ *    'supported': Only show the latest release from each supported branch.
  *    'all': Include all releases.
  *
  * @param $release_type
@@ -1641,11 +1646,15 @@ function project_release_table($project,
   if (empty($title)) {
     $title = t('Version');
   }
+  // Can the current user edit releases for this project?
+  $can_edit = node_access('update', $project);
+
   // Generate the cache ID.
-  $cid = 'table:'. $project->nid .':'. $table_type .':'. $release_type .':'. $title .':'. (int)$print_size;
+  $cid = 'table:'. $project->nid .':'. $table_type .':'. $release_type .':'. $title .':'. (int)$print_size .':'. (int)$can_edit;
   if ($cached = cache_get($cid, 'cache_project_release')) {
-    return $cached->data;
+    // return $cached->data;
   }
+
   $select = $join = $where = $order_by = '';
   $tids = project_release_compatibility_list();
   if ($tids) {
@@ -1660,34 +1669,45 @@ function project_release_table($project,
     }
   }
 
-  if ($table_type == 'recommended') {
-    if ($tids) {
-      $join .= ' INNER JOIN {project_release_supported_versions} prsv ON prsv.nid = r.pid AND prsv.tid = tn.tid AND prsv.major = r.version_major AND prsv.recommended = 1 ';
+  if ($tids) {
+    $selects[] = 'prsv.supported';
+    $selects[] = 'prsv.recommended';
+    $selects[] = 'prsv.snapshot';
+    $join .= ' INNER JOIN {project_release_supported_versions} prsv ON prsv.nid = r.pid AND prsv.tid = tn.tid AND prsv.major = r.version_major ';
+    if ($table_type == 'recommended') {
+      $join .= 'AND prsv.recommended = 1 ';
     }
-    else {
-      // TODO
+    elseif ($table_type == 'supported') {
+      $join .= 'AND prsv.supported = 1 ';
     }
   }
+  else {
+    // TODO
+  }
 
   switch ($release_type) {
     case 'official':
       $where = 'AND r.rebuild <> 1';
       break;
     case 'snapshot':
-      $where = 'AND r.rebuild = 1';
+      // For snapshot tables, restrict to snapshot nodes from branches where
+      // the maintainer wants the snapshot visible.
+      $where = 'AND r.rebuild = 1 AND prsv.snapshot = 1';
       break;
     case 'all':
-        // If we're generating the default releases table, we want the
-        // dev snapshots to be first in the query results, so that we
-        // skip over them and only show official releases (if any).
-      $orderby[] = 'r.rebuild'. (($table_type == 'recommended') ? ' DESC' : '');
+      // If we're generating the default releases table, we want the
+      // dev snapshots to be last in the query results, so that we
+      // only show them if there's nothing else.
+      if ($table_type == 'recommended') {
+        $orderby[] = 'r.rebuild ASC';
+      }
       break;
   }
 
-  $orderby[] = 'r.version_major';
-  $orderby[] = 'r.version_minor';
-  $orderby[] = 'r.version_patch';
-  $orderby[] = 'r.file_date';
+  $orderby[] = 'r.version_major DESC';
+  $orderby[] = 'r.version_minor DESC';
+  $orderby[] = 'r.version_patch DESC';
+  $orderby[] = 'r.file_date DESC';
 
   if ($orderby) {
     $order_by = ' ORDER BY '. implode(', ', $orderby);
@@ -1695,73 +1715,59 @@ function project_release_table($project,
   if ($selects) {
     $select = implode(', ', $selects) .',';
   }
+
   $result = db_query(db_rewrite_sql(
     "SELECT n.nid, n.created, $select r.* FROM {node} n ".
-    "INNER JOIN {project_release_nodes} r ON r.nid = n.nid ". $join .
-    "WHERE (r.pid = %d) AND (n.status = 1) ". $where .' '. $order_by),
+    "INNER JOIN {project_release_nodes} r ON r.nid = n.nid $join ".
+    "WHERE (r.pid = %d) AND (n.status = 1) $where $order_by"),
     $project->nid);
 
-  if (!db_num_rows($result) && $release_type != 'official' && $tids) {
-    // Work-around for releases without a compatibility term
-    // (e.g. unclassified HEAD releases on drupal.org).
-    $result = db_query(db_rewrite_sql(
-      "SELECT n.nid, n.created, r.* FROM {node} n ".
-      "INNER JOIN {project_release_nodes} r ON r.nid = n.nid ".
-      "WHERE (r.pid = %d) AND (n.status = 1) ". $where), $project->nid);
-  }
-
-  $items = array();
-  $can_edit = node_access('update', $project);
-
+  $rows = array();  // Rows for the download table.
+  $seen = array();  // Keeps track of which versions we already saw.
   while ($release = db_fetch_object($result)) {
-    $links = array();
-    if (!empty($release->file_path)) {
-      $links['project_release_download'] = theme('project_release_download_link', $release->file_path, t('Download'), TRUE);
-    }
-    $links['project_release_notes'] = array(
-      'title' => t('Release notes'),
-      'href' => "node/$release->nid",
-    );
-    if ($can_edit) {
-      $links['project_release_edit'] = array(
-        'title' => t('Edit'),
-        'href' => "node/$release->nid/edit",
-      );
-    }
-    if (!isset($items[$release->tid]) || !is_array($items[$release->tid])) {
-      $items[$release->tid] = array();
+    $tid = $release->tid;
+    $major = $release->version_major;
+    $recommended = false;
+    if ($table_type == 'supported') {
+      // Supported version can be multiple majors per tid.
+      if (empty($seen[$tid])) {
+        $seen[$tid] = array();
+      }
+      if (empty($seen[$tid][$major])) {
+        $seen[$tid][$major] = 1;
+        if ($release->recommended) {
+          $recommended = true;
+        }
+      }
+      else {
+        // We already know the supported release for this tid/major, go on.
+        continue;
+      }
     }
-
-    $row = array(
-      // class of <tr>
-      'class' => $release->rebuild ? 'release-dev' : 'release',
-      'data' => array(
-        array(
-          'class' => 'release-title',
-          'data' => l($release->version, "node/$release->nid"),
-        ),
-        array(
-          'class' => 'release-date',
-          'data' => !empty($release->file_path) ? format_date($release->file_date, 'custom', 'Y-M-d') : format_date($release->created, 'custom', 'Y-M-d'),
-        ),
-      ),
-    );
-    if ($print_size) {
-      $row['data'][] = array(
-        'class' => 'release-size',
-        'data' => !empty($release->file_path) ? format_size(filesize(file_create_path($release->file_path))) : t('n/a'),
-      );
+    else {
+      if (empty($seen[$tid])) {
+          // Only one major per tid, so the row lives here.
+        $seen[$tid] = 1;
+        if ($release->recommended) {
+          $recommended = true;
+        }
+      }
+      elseif ($table_type == 'recommended') {
+        // We already know the recommended release for this tid and that's all
+        // we want in the table, so skip this release.
+        continue;
+      }
     }
-    $row['data'][] = array(
-      'class' => 'release-links',
-      'data' => theme('links', $links),
-    );
-    $items[$release->tid][] = $row;
+    // If we're still here, we need to add the row to the table.
+    // TODO: only mark the first as recommended...
+    $rows[] = _project_release_download_table_row($release, $recommended, $can_edit, $print_size);
   }
+
   $header = array(
     array(
       'class' => 'release-title',
-      'data' => $title),
+      'data' => $title,
+    ),
     array(
       'class' => 'release-date',
       'data' => t('Date'),
@@ -1777,20 +1783,14 @@ function project_release_table($project,
     'class' => 'release-links',
     'data' => t('Links'),
   );
+  $header[] = array(
+    'class' => 'release-status',
+    'data' => t('Status'),
+  );
 
-  $rows = array();
-  foreach ($items as $tid => $item) {
-    if ($table_type == 'recommended') {
-      // We only want the last entry in the array.
-      $rows[] = array_pop($item);
-    }
-    else {
-      $rows = array_merge($rows, $item);
-    }
-  }
   $output = '';
   if (!empty($rows)) {
-    $output = theme('table', $header, $rows, array('class' => 'releases'));
+    $output = theme('table', $header, $rows, array('class' => 'releases system-status-report'));
   }
   // Default cache time is 12 hours - will be cleared by the packaging script
   cache_set($cid, 'cache_project_release', $output, time() + 43200);
@@ -1798,6 +1798,97 @@ function project_release_table($project,
 }
 
 /**
+ * Helper function to return an individual row for the download table.
+ *
+ * @param $release
+ *   The release object queried from the database.
+ * @param $recommended
+ *   Boolean indicating if this release is the currently recommended one.
+ * @param $can_edit
+ *   Boolean indicating if the current user can edit the release.
+ * @param $print_size
+ *   Boolean indicating if the size of the download should be printed.
+ */
+function _project_release_download_table_row($release, $recommended = false, $can_edit = false, $print_size = true) {
+  static $icons = array();
+  if (empty($icons)) {
+    $icons = array(
+      'ok' => theme('image', 'misc/watchdog-ok.png', t('ok'), t('ok')),
+      'warning' => theme('image', 'misc/watchdog-warning.png', t('warning'), t('warning')),
+      'error' => theme('image', 'misc/watchdog-error.png', t('error'), t('error')),
+    );
+  }
+  $links = array();
+  if (!empty($release->file_path)) {
+    $links['project_release_download'] = theme('project_release_download_link', $release->file_path, t('Download'), TRUE);
+  }
+  $links['project_release_notes'] = array(
+    'title' => t('Release notes'),
+    'href' => "node/$release->nid",
+  );
+  if ($can_edit) {
+    $links['project_release_edit'] = array(
+      'title' => t('Edit'),
+      'href' => "node/$release->nid/edit",
+    );
+  }
+  // Figure out the class for the table row
+  $row_class = $release->rebuild ? 'release-dev' : 'release';
+  // Now, set the row color and help text, based on the release attributes.
+  if (!$release->supported) {
+    $reason = t('Unsupported');
+    $classification = 'error';
+  }
+  elseif ($release->rebuild) {
+    $reason = t('Development snapshot');
+    $classification = 'error';
+  }
+  elseif ($recommended) {
+    $reason = t('Recommended');
+    $classification = 'ok';
+  }
+  else {
+    // Supported, but not recommened, official release.
+    $reason = t('Supported');
+    $classification = 'warning';
+  }
+
+  $row = array(
+    // class of <tr>
+    'class' => $row_class .' '. $classification,
+    'data' => array(
+      array(
+        'class' => 'release-title',
+        'data' => l($release->version, "node/$release->nid"),
+      ),
+      array(
+        'class' => 'release-date',
+        'data' => !empty($release->file_path) ? format_date($release->file_date, 'custom', 'Y-M-d') : format_date($release->created, 'custom', 'Y-M-d'),
+      ),
+    ),
+  );
+  if ($print_size) {
+    $row['data'][] = array(
+      'class' => 'release-size',
+      'data' => !empty($release->file_path) ? format_size(filesize(file_create_path($release->file_path))) : t('n/a'),
+      );
+  }
+  $row['data'][] = array(
+    'class' => 'release-links',
+    'data' => theme('links', $links),
+  );
+  $row['data'][] = array(
+    'class' => 'release-reason',
+    'data' => $reason,
+  );
+  $row['data'][] = array(
+    'class' => 'release-icon',
+    'data' => $icons[$classification],
+  );
+  return $row;
+}
+
+/**
  * Implementation of hook_taxonomy().
  */
 function project_release_taxonomy($op, $type, $object = NULL) {
