<?php
/*
Plugin Name: Smart Archives
Version: 2.0
Plugin URI: http://justinblanton.com/projects/smartarchives/
Description: A simple, clean, and future-proof way to present your archives.
Author: Justin Blanton
Author URI: http://justinblanton.com
*/

// add hook
add_action('publish_post''smartArchives'); // generate archives after a new post
                        
// display archives
function displayArchives() {  
    
$file '/path/to/archives.txt';
    
$fh fopen($file'r') or die('<p> <br /><br />*******************<br /> COULD NOT OPEN FILE <br /> ******************* </p>
        <p>If you are seeing this error it probably means that you have not yet <em>created</em> the archives file (just referenced it).  
        To remedy the situation, you can do one of the following:</p>
        <p> 1.)  Publish a new post (this will cause smartArchives() to run, which will create/overwrite the archives file).</p>
        <p> 2.)  Run the <em>touch</em> command from a shell (i.e., "touch archives.txt").  This will cause the error to go away, but the archives page still will not actually display anything until you publish a new post.</p>
        <p> 3.)  Create a one-line PHP script that calls smartArchives() (e.g., &lt;php smartArchives(); ?&gt;) and access this file through your web browser.  This obviously will run the smartArchives() function, which will create/overwrite the archives file.</p>'
);
    
$data fread($fhfilesize($file)) or die('could not read file!'); 
    echo 
$data
    
fclose($fh);
}

// generate archives
function smartArchives() {

    global 
$wpdb$PHP_SELF;
    
setlocale(LC_ALL,WPLANG); // set localization language; please see instructions
    
$now gmdate("Y-m-d H:i:s",(time()+((get_settings('gmt_offset'))*3600)));  // get the current GMT date
    
$bogusDate "/01/2001"// used for the strtotime() function below    
    
    
$format='both'// the format of the archives; it can be block, list, or both
    
$catID=''// the category(ies) you do *not* want to be displayed in your archives

    
$file '/path/to/archives.txt';
    
$fh fopen($file'w') or die('could not open file!');
    
    
$yearsWithPosts $wpdb->get_results("
        SELECT distinct year(post_date) AS `year`, count(ID) as posts
        FROM $wpdb->posts 
        WHERE post_type = 'post' 
        AND post_status = 'publish' 
        GROUP BY year(post_date) 
        ORDER BY post_date DESC"
);
    
    foreach (
$yearsWithPosts as $currentYear) {
        
        for (
$currentMonth 1$currentMonth <= 12$currentMonth++) {
            
            
$monthsWithPosts[$currentYear->year][$currentMonth] = $wpdb->get_results("
            SELECT ID, post_title FROM $wpdb->posts 
            WHERE post_type = 'post'
            AND post_status = 'publish' 
            AND year(post_date) = '$currentYear->year' 
            AND month(post_date) = '$currentMonth'            
            ORDER BY post_date DESC"
);
        }
    }
    
    if ((
$format == 'both') || ($format == 'block')) { // check to see if we are supposed to display the block
        
        // get the shortened month name; strftime() should localize
        
for($currentMonth 1$currentMonth <= 12$currentMonth++) $shortMonths[$currentMonth] = ucfirst(strftime("%b"strtotime("$currentMonth"."$bogusDate")));
        
        if (
$yearsWithPosts) {

            foreach (
$yearsWithPosts as $currentYear) {
                
                
$archives .= '<strong><a href="'.get_year_link($currentYear->year$currentYear->year).'">'.$currentYear->year.'</a>:</strong> ';
                
                for (
$currentMonth 1$currentMonth <= 12$currentMonth++) {
                    
                    if (
$monthsWithPosts[$currentYear->year][$currentMonth]) $archives .= '<a href="'.get_month_link($currentYear->year$currentMonth).'">'.$shortMonths[$currentMonth].'</a> ';
                    else 
$archives .= '<span class="emptymonth">'.$shortMonths[$currentMonth].'</span> ';
                    
                }                
                
$archives .= '<br />';
            }            
            
$archives .= '<br /><br />';        
        }
    
        if (
$format == 'block'fwrite($fh$archives); // write archives to file if not displaying list format
       
    
}    
    
    if ((
$format == 'both') || ($format == 'list')) { //check to see if we are supposed to display the list
        
        // get the month name; strftime() should localize
        
for($currentMonth 1$currentMonth <= 12$currentMonth++) $monthNames[$currentMonth] = ucfirst(strftime("%B"strtotime("$currentMonth"."$bogusDate")));
        
        if (
$yearsWithPosts) {
            
            if (
$catID != '') { // at least one category was specified to be excluded
                
                
$catIDs explode(" "$catID); // put the category(ies) into an array
                
                
foreach($yearsWithPosts as $currentYear) {
                    
                    for (
$currentMonth 12$currentMonth >= 1$currentMonth--) {
                        
                        if (
$monthsWithPosts[$currentYear->year][$currentMonth]) {
                            
$archives .= '<h2><a href="'.get_month_link($currentYear->year$currentMonth).'">'.$monthNames[$currentMonth].' '.$currentYear->year.'</a></h2>';
                            
$archives .= '<ul>';
                            
                            foreach (
$monthsWithPosts[$currentYear->year][$currentMonth] as $post) { 
                                
                                if (
$post->post_date <= $now) {
                                    
$cats wp_get_post_categories($post->ID);
                                    
$found false;
                                    
                                    foreach (
$cats as $cat) if (in_array($cat$catIDs)) $found true;
                                    
                                    if (!
$found$archives .= '<li><a href="'.get_permalink($post->ID).'">'.$post->post_title.'</a></li>';
                                } 
                            }   
                            
$archives .= '</ul>';  
                        }
                    }
                }
            }
            
            else { 
// we don't need to exclude any categories
            
                
foreach($yearsWithPosts as $currentYear) {
                    
                    for (
$currentMonth 12$currentMonth >= 1$currentMonth--) {
                        
                        if (
$monthsWithPosts[$currentYear->year][$currentMonth]) {
                            
$archives .= '<h2><a href="'.get_month_link($currentYear->year$currentMonth).'">'.$monthNames[$currentMonth].' '.$currentYear->year.'</a></h2>'
                            
$archives .= '<ul>';
                            
                            foreach (
$monthsWithPosts[$currentYear->year][$currentMonth] as $post$archives .= '<li><a href="'.get_permalink($post->ID).'">'.$post->post_title.'</a></li>';
                            
$archives .= '</ul>';
                        }
                    }
                }
            }                               
        }                     
        
fwrite($fh$archives); // write archives to file
    
}
    
fclose($fh); // close archives file    
}?>