Archives for each category on WP Multisite

I thought I’d let you know how I resolved this.

After some discussion with a colleague, he made the point that adding a trailing year to the url, doesn’t affect the page displayed (I haven’t had time to find out the rationale for this yet) so:

/category/subcat/2011/

displays the same page as

/category/subcat/

This meant that I could parse the url and take the year from it and add it to the query.

I added this to the header to parse the url (I’m sure there are more efficient ways, but this worked well for me):

$current = $_SERVER['REQUEST_URI']; // get the url

$parts = explode("https://wordpress.stackexchange.com/",$current); // break the url down into parts
$parts = array_slice($parts, 1, -1); // for some reason, first and last array items were blank, so trim them

$pattern = "/\d{4}/"; // set the pattern to match a 4 digit number
$last = end($parts); // get the last item in the array
$year=""; // set the year variable to be empty

if(preg_match($pattern, $last)) {  // test the last array item against the 4 digit pattern
    $year = $last; // if it is a number, then set the year variable to that value
    $parent_parts = array_slice($parts, 0, -1); // as I need this to work with both the url having a number at the end and on the parent page too (without a year in the URL), make the parent part path by trimming out the year component

    $parent = implode("https://wordpress.stackexchange.com/",$parent_parts); // remake the url parts
    $parent="https://wordpress.stackexchange.com/".$parent."https://wordpress.stackexchange.com/";  // add leading and trailing slashes
} else {
    $parent = $current;  // if the test doesn't find a year, just set the parent to the REQUEST_URI
}

This might seem overly complex for what it does, but the logic works. If I do a test for a year on:

/category/subcat/

I need the code to know what to do with this bit. As I’m always going to need this part of the url, if the url is:

/category/subcat/2011/

I’ll need to trim 2011 off of it. This becomes more apparent further down.

I changed the title display from:

<h2><?php the_title(); ?></h2>

to:

<h2><?php echo get_the_title();
if($year !== ''){
    echo ': Archives '.$year;
}
?></h2>

This just means that on the parent page, I output the title and on a year sub-page, I can add in an “: Archives 2011” to the end of it to make it look like a proper archive.

I have a dropdown for the year at the top of the page. Previously this was populated with wp_get_archives, but I’ve scrapped that now. Now I need to have a first item called “All” which will revert to the parent, full list of posts and each subsequent item in the dropdown is a year.

<select name="archive-dropdown" onchange="document.location.href=this.options[this.selectedIndex].value;"> // standard wp_get_archives dropdown jump functionality
        <option value="<?php echo get_bloginfo('url'); ?><?php echo $parent; ?>">All</option> // the "All" option, with the parts formulating the url
        <?php
        $years = $wpdb->get_col("SELECT DISTINCT YEAR(post_date) FROM $wpdb->posts ORDER BY post_date DESC"); // getting a list of years for all the posts in the category
        foreach($years as $list_year) : 
        if($list_year == $year) {
            $select=" selected="selected""; // ensures that the current year stays selected
        } else {
            $select="";
        } ?>

        <option value="<?php echo get_bloginfo('url'); ?><?php echo $parent; ?><?php echo $list_year; ?>/"<?php echo $select; ?>><?php echo $list_year; ?></option> // populates the option field
        <?php endforeach; ?>
</select>

Pretty straightforward stuff. I got most of the dropdown code from: http://wordpress.org/support/topic/archives-by-year-this-is-different

I probably need to add a category component to the MySQL query.

Finally, I changed the WP_Query, to include a year attribute. As this is left blank when the parent page is selected, it defaults to latest date. Otherwise, it shows just the year selected:

$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : false;
$args = array('cat' => $cat, 'posts_per_page' => '10', 'paged' => $paged, 'year' => $year );
$query = new WP_Query($args);

Just for good measure, I’ve left in the paging, which I use with the wp_pagenavi plugin.

The lesson here is that WordPress Multisite archiving is appalling. DIY is much better. I hope this helps someone else out there.

UPDATE: Have run into major problems with pagination in this regard. There seems to be no easy way around this, though working on a solution. WordPress just does not seem to play nice with category specific archives AND pagination.