--- C:/Documents and Settings/Administrator/Desktop/archive/archive.inc	Tue May 01 08:09:47 2007
+++ C:/Apache2/myblog/modules/archive/archive.inc	Wed May 02 02:53:36 2007
@@ -1,5 +1,5 @@
 <?php
-// $Id: archive.inc,v 1.1.2.5 2007/05/01 12:09:47 goba Exp $
+// $Id$
 
 /**
  * * Fetch nodes for the selected date, or current date if none selected.
@@ -13,12 +13,12 @@
  * @return
  *   A string with the themed page
  */
-function _archive_page($year = NULL, $month = NULL, $day = NULL) {
-  $date = _archive_date($year, $month, $day);
-  $output = theme('archive_navigation', $date);
+function _archive_page($type = 'all', $year = NULL, $month = NULL, $day = NULL) {
+  $date = _archive_date($type, $year, $month, $day);
+  $output = theme('archive_navigation', $type, $date);
 
   $nodes = variable_get('default_nodes_main', 10);
-  $query = _archive_query($date);
+  $query = _archive_query($type, $date);
   $result = pager_query(db_rewrite_sql(array_shift($query)), $nodes, 0, NULL, $query);
 
   if (db_num_rows($result)) {
@@ -27,6 +27,15 @@
     }
     $output .= theme('pager', NULL, $nodes);
   }
+  elseif ($date->days[$date->day] > 0) {
+    drupal_goto(_archive_url('all', $date->year, $date->month, $date->day));
+  }
+  elseif ($date->months[$date->month] > 0) {
+    drupal_goto(_archive_url('all', $date->year, $date->month));
+  }
+  elseif ($date->year[$date->year] > 0) {
+    drupal_goto(_archive_url('all', $date->year));
+  }
 
   return $output;
 }
@@ -44,7 +53,7 @@
  * @return
  *   A date object with GMT date values and a timezone value
  */
-function _archive_date($year = NULL, $month = NULL, $day = NULL) {
+function _archive_date($type, $year = NULL, $month = NULL, $day = NULL) {
   static $date = null;
 
   if ($date != null) {
@@ -74,9 +83,9 @@
   $date->month_last_day = gmdate('t', $date->start_of_month);
   $date->end_of_month   = gmmktime(23, 59, 59, $date->month, $date->month_last_day, $date->year);
 
-  $date->years  = _archive_years($date);
-  $date->months = _archive_months($date);
-  $date->days   = _archive_days($date);
+  $date->years  = _archive_years($type, $date);
+  $date->months = _archive_months($type, $date);
+  $date->days   = _archive_days($type, $date);
 
   return $date;
 }
@@ -90,8 +99,7 @@
  * @return
  *    An array of (query, param_start, param_end)
  */
-function _archive_query($date) {
-
+function _archive_query($type, $date) {
   if ($date->day > 0 && $date->month > 0) {
     // Confine the display interval to only one day
     $start = gmmktime(0, 0, 0, $date->month, $date->day, $date->year);
@@ -107,20 +115,56 @@
     $start = gmmktime(0, 0, 0, 1, 1, $date->year);
     $end   = gmmktime(0, 0, 0, 1, 1, $date->year + 1);
   }
+  $final_types = _archive_types_sql_string($type);
+  return array('SELECT n.nid, n.type FROM {node} n WHERE n.status = 1 '. $final_types .'AND n.created >= %d AND n.created < %d ORDER BY n.created DESC', $start - $date->tz, $end - $date->tz);
+}
 
-  return array('SELECT n.nid, n.type FROM {node} n WHERE n.status = 1 AND n.created >= %d AND n.created < %d ORDER BY n.created DESC', $start - $date->tz, $end - $date->tz);
+/**
+ * Builds a SQL statement to check that the appropriate
+ * node types are being returned 
+ *
+ * @param $type
+ *    The current type we're filtering
+ * @return
+ *    A SQL string
+ */
+function _archive_types_sql_string($type){
+  // Validate type and specify node types to include
+  $final_types = '';
+  if (_archive_validate_type($type) && $type != 'all') {
+    $final_types = $type; 
+  }
+  else {
+    $types = variable_get('archive_type_filters', array());
+    // If no checkboxes selected
+    if (!array_key_exists('0', $types)) {
+      foreach ($types as $key => $value) {
+        if (!$value) {
+          unset($types[$key]);
+        }
+      }
+      $final_types = join(array_keys($types), '", "');
+    }
+  }
+  if (strlen($final_types) > 0) {
+    $final_types = 'AND n.type IN ("' . $final_types . '") ';
+  }
+  return $final_types;
 }
 
 /**
  * Returns the range of years with nodes.
  *
+ * @param $type
+ *    The object that is being filtered
  * @param $date
  *    A date object obtained from _archive_date()
  * @return
  *    An array of the (first year with posts, last year with posts).
  */
-function _archive_years($date) {
-  $result = db_query(db_rewrite_sql('SELECT MIN(created) AS min_date, MAX(created) AS max_date FROM {node} n WHERE n.status = 1'));
+function _archive_years($type, $date) {
+  $final_types = _archive_types_sql_string($type);
+  $result = db_query(db_rewrite_sql('SELECT MIN(created) AS min_date, MAX(created) AS max_date FROM {node} n WHERE n.status = 1 ' . $final_types));
   $min_max = db_fetch_object($result);
   return array(gmdate('Y', $min_max->min_date + $date->tz), gmdate('Y', $min_max->max_date + $date->tz));
 }
@@ -129,17 +173,20 @@
  * Returns the months of a given year which have nodes.
  * Note: FROM_UNIXTIME could be used, but it is MySQL only and has timezone issues.
  *
+ * @param $type
+ *    The current type we're filtering
  * @param $date
  *    A date object obtained from _archive_date()
  * @return
  *    An array of months with number of posts for each.
  */
-function _archive_months($date) {
+function _archive_months($type, $date) {
+  $final_types = _archive_types_sql_string($type);
   $months_with_posts = array();
   foreach (range(1, 12) as $month) {
     $start  = gmmktime(0, 0, 0, $month, 1, $date->year) - $date->tz;
     $end    = gmmktime(0, 0, 0, $month + 1, 1, $date->year) - $date->tz;
-    $result = db_query(db_rewrite_sql('SELECT COUNT(*) AS count FROM {node} n WHERE n.status = 1 AND n.created >= %d AND n.created < %d'), $start, $end);
+    $result = db_query(db_rewrite_sql('SELECT COUNT(*) AS count FROM {node} n WHERE n.status = 1 ' . $final_types . 'AND n.created >= %d AND n.created < %d'), $start, $end);
     $row = db_fetch_object($result);
     $months_with_posts[$month] = $row->count;
   }
@@ -149,14 +196,17 @@
 /**
  * Returns the days of a given month which have nodes.
  *
+ * @param $type
+ *    The current node type we're filtering
  * @param $date
  *    A date object obtained from _archive_date()
  * @return
  *    An array of days having posts with number of posts for each.
  */
-function _archive_days($date) {
+function _archive_days($type, $date) {
+  $final_types = _archive_types_sql_string($type);
 
-  $result = db_query(db_rewrite_sql('SELECT n.nid, n.created FROM {node} n WHERE n.status = 1 AND n.created BETWEEN %d AND %d ORDER BY n.created'), $date->start_of_month - $date->tz, $date->end_of_month - $date->tz);
+  $result = db_query(db_rewrite_sql('SELECT n.nid, n.created FROM {node} n WHERE n.status = 1 ' . $final_types . 'AND n.created BETWEEN %d AND %d ORDER BY n.created'), $date->start_of_month - $date->tz, $date->end_of_month - $date->tz);
 
   $days_with_posts = array();
   while ($day_with_post = db_fetch_object($result)) {
@@ -173,6 +223,58 @@
 }
 
 /**
+ * Returns the different node types that have nodes
+ *
+ * @param $date
+ *    A date object obtained from _archive_date()
+ * @return
+ *    An array of node-types to number of posts of that type
+ */
+function _archive_node_types($date) {
+  
+  $types = variable_get('archive_type_filters', array());
+  if ($types[0] == '1') {
+    return array();
+  }
+  foreach ($types as $key => $value) {
+    if (!$value) {
+      unset($types[$key]);
+    }
+    else {
+      $types[$key] = 0;
+    }
+  }
+  if ($date->day > 0 && $date->month > 0) {
+    // Confine the display interval to only one day
+    $start = gmmktime(0, 0, 0, $date->month, $date->day, $date->year);
+    $end   = gmmktime(0, 0, 0, $date->month, $date->day + 1, $date->year);
+  }
+  elseif ($date->month > 0) {
+    // Confine the display interval to one month
+    $start = gmmktime(0, 0, 0, $date->month, 1, $date->year);
+    $end   = gmmktime(0, 0, 0, $date->month + 1, 1, $date->year);
+  }
+  else {
+    // Confine the display interval to one year
+    $start = gmmktime(0, 0, 0, 1, 1, $date->year);
+    $end   = gmmktime(0, 0, 0, 1, 1, $date->year + 1);
+  }
+  $result = db_query('SELECT t.type, t.name, COUNT(n.nid) AS node_count FROM {node} n INNER JOIN {node_type} t ON t.type = n.type WHERE n.status = 1 AND t.type IN ("' . join(array_keys($types), '", "') . '") AND n.created BETWEEN %d AND %d GROUP BY n.type ORDER BY n.created', $start - $date->tz, $end - $date->tz);
+  
+  $n_types['all'] = array('count' => 0,
+                          'name'  => t('All'));
+              
+  while ($row = db_fetch_array($result)) {
+    $n_types[$row['type']] = array('count' => $row['node_count'],
+                                   'name'  => $row['name']);
+    $n_types['all']['count'] += $row['node_count'];
+  }
+  
+  ksort($n_types);
+  return $n_types;
+}
+
+/**
  * Check if given year is valid for a Drupal archive
  *
  * @param $year
@@ -221,6 +323,27 @@
 }
 
 /**
+ * Check if given node type is valid for a Drupal archive
+ *
+ * @param $type
+ *    The type to check
+ * @return
+ *    TRUE or FALSE
+ */
+function _archive_validate_type($type) {
+  $types = variable_get('archive_type_filters', array());
+  foreach ($types as $key => $value) {
+    if (!$value) {
+      unset($types[$key]);
+    }
+    else {
+      $types[$key] = 0;
+    }
+  }
+  return in_array($type, array_keys($types));
+}
+
+/**
  * Generate an archive URL based on the $y, $m and $d
  * provided, falling back on the $date properties if
  * an invalid date is specified.
@@ -229,6 +352,8 @@
  * because those could be zero, if not defined from the
  * URL.
  *
+ * @param $type
+ *    The node type to use if valid
  * @param $y
  *    The year to use if valid
  * @param $m
@@ -238,9 +363,16 @@
  * @return
  *    A string with the generated archive URL
  */
-function _archive_url($date, $y = 0, $m = 0, $d = 0) {
+function _archive_url($type, $date, $y = 0, $m = 0, $d = 0) {
   $url = 'archive';
 
+  if (_archive_validate_type($type)) {
+    $url .= '/' . $type;
+  }
+  else {
+    $url .= '/all';
+  }
+
   if (_archive_validate_year($y)) {
     $url .= '/'. $y;
     if (_archive_validate_month($m)) {
@@ -285,16 +417,23 @@
  * Theme the archive navigation with years, months and dates by default.
  * @ingroup themeable
  */
-function theme_archive_navigation($date) {
+function theme_archive_navigation($type, $date) {
   $output  = "<div id=\"archive-container\"><dl><dt>". t('Date') ."</dt><dd>\n";
-  $output .= theme('archive_navigation_years', $date);
+  $output .= theme('archive_navigation_years', $type, $date);
   if (_archive_validate_year($date->year)) {
-    $output .= theme('archive_navigation_months', $date);
+    $output .= theme('archive_navigation_months', $type, $date);
   }
   if (_archive_validate_month($date->month)) {
-    $output .= theme('archive_navigation_days', $date);
+    $output .= theme('archive_navigation_days', $type, $date);
+  }
+  $output .= "</dd>";
+  // Only display node type filter if more than one node type represented
+  if (sizeof(_archive_node_types($date)) > 2) {
+    $output .= "<dt>". t('Type') ."</dt><dd>\n";
+    $output .= theme('archive_navigation_node_types', $type, $date);
+    $output .= "</dd>";
   }
-  $output .= "</dd></dl></div>\n";
+  $output .= "</dl></div>\n";
   return $output;
 }
 
@@ -302,7 +441,7 @@
  * Theme the list of years for the archive navigation.
  * @ingroup themeable
  */
-function theme_archive_navigation_years($date) {
+function theme_archive_navigation_years($type, $date) {
   $num_to_display = 3;
   $right_offset = min(gmdate('Y', $date->now + $date->tz) - $date->year, 2);
   $left_offset  = $num_to_display - $right_offset;
@@ -320,7 +459,7 @@
 
     $name = gmdate('Y', gmmktime(0, 0, 0, 1, 1, $year));
     if (min($date->years) <= $year && $year <= max($date->years)) {
-        $output .= "<li$class>". l($name, _archive_url($date, $year)). "</li>\n";
+        $output .= "<li$class>". l($name, _archive_url($type, $date, $year)). "</li>\n";
     }
     else {
       $output .= "<li$class>$name</li>\n";
@@ -335,13 +474,13 @@
  * Theme the list of months for the archive navigation.
  * @ingroup themeable
  */
-function theme_archive_navigation_months($date) {
+function theme_archive_navigation_months($type, $date) {
   $output = "<ul id=\"archive-months\">\n";
   foreach (range(1, 12) as $month) {
     $posts = !empty($date->months[$month]) ? $date->months[$month] : 0;
     $class = ($month == $date->month) ? ' class="selected"' : '';
     $name = t(gmdate('M', gmmktime(0, 0, 0, $month, 1, $date->year)));
-    $output .= "<li$class>". ($posts > 0 ? l($name, _archive_url($date, 0, $month), array('title' => format_plural($posts, "1 post", "@count posts"))) : $name) ."</li>\n";
+    $output .= "<li$class>". ($posts > 0 ? l($name, _archive_url($type, $date, 0, $month), array('title' => format_plural($posts, "1 post", "@count posts"))) : $name) ."</li>\n";
   }
   $output .= "</ul>\n";
   return $output;
@@ -351,7 +490,7 @@
  * Theme the list of days for the archive navigation.
  * @ingroup themeable
  */
-function theme_archive_navigation_days($date) {
+function theme_archive_navigation_days($type, $date) {
   $output = "";
   $day_stop = gmdate('t', gmmktime(0, 0, 0, $date->month, 1, $date->year));
   $output = "<ul id=\"archive-days\">\n";
@@ -360,8 +499,37 @@
     $posts = !empty($date->days[$day]) ? $date->days[$day] : 0;
     $class = ($day == $date->day) ? ' class="selected"' : '';
     $name = gmdate('d', gmmktime(0, 0, 0, $date->month, $day, $date->year));
-    $output .= "<li$class>". ($posts ? l($name, _archive_url($date, 0, 0, $day), array("title" => format_plural($posts, "1 post", "@count posts"))) : $name) ."</li>\n";
+    $output .= "<li$class>". ($posts ? l($name, _archive_url($type, $date, 0, 0, $day), array("title" => format_plural($posts, "1 post", "@count posts"))) : $name) ."</li>\n";
+  }
+  $output .= "</ul>\n";
+  return $output;
+}
+
+/**
+ * Theme the list of node types for the archives
+ * @ingroup themeable
+ */
+function theme_archive_navigation_node_types($type, $date) {
+  
+  $output = "";
+  $output = "<ul id=\"archive-node_types\">\n";
+
+  $types_count = _archive_node_types($date);
+  foreach ($types_count as $ft_key => $ft_value) {
+    if (!$ft_value['count']) {
+      continue;
+    }
+    $class = ($ft_key == $type ? ' class="selected"' : '');
+    $name = $ft_value['name'];
+    if ($types_count[$ft_key]['count'] > 0) {
+      $output .= "<li$class>". l($name, _archive_url($ft_key, $date, $date->year, $date->month, $date->day), array("title" => format_plural($types_count[$ft_key]['count'], "1 post", "@count posts"))) ."</li>\n";
+    }
+    else {
+      $output .= "<li$class>$name</li>\n";
+    }
   }
   $output .= "</ul>\n";
   return $output;
 }
+
+?>
\ No newline at end of file
