From ab4397c05a5b712526615c6b3e69fd72b8036abf Mon Sep 17 00:00:00 2001
From: Erick Hitter <ehitter@gmail.com>
Date: Sun, 3 Jun 2012 18:58:25 -0400
Subject: [PATCH] Initial plugin commit.

---
 date-based-taxonomy-archives.php | 294 +++++++++++++++++++++++++++++++
 1 file changed, 294 insertions(+)
 create mode 100644 date-based-taxonomy-archives.php

diff --git a/date-based-taxonomy-archives.php b/date-based-taxonomy-archives.php
new file mode 100644
index 0000000..e292af7
--- /dev/null
+++ b/date-based-taxonomy-archives.php
@@ -0,0 +1,294 @@
+<?php
+/*
+Plugin Name: Date-based Taxonomy Archives
+Plugin URI:
+Description: Renders an unordered list of years with months, linked to corresponding date-based taxonomy archive, nested therein.
+Author: Erick Hitter
+Version: 0.1
+Author URI: http://www.ethitter.com/
+*/
+
+class Date_Based_Taxonomy_Archives {
+	/**
+	 * Class variables
+	 */
+	var $defaults = array(
+		'taxonomies' => false,
+		'show_post_count' => false,
+		'limit' => '',
+		'before' => '',
+		'after' => '',
+		'echo' => true
+	);
+
+	var $cache_key_incrementor = 'incrementor';
+	var $cache_group = 'date_based_taxonomy_archives';
+
+	var $filter_archive_links = false;
+
+	/**
+	 * Register actions and filters
+	 *
+	 * @uses add_action, add_filter
+	 * @return null
+	 */
+	function __construct() {
+		add_action( 'transition_post_status', array( $this, 'action_transition_post_status' ), 50, 2 );
+
+		add_filter( 'date_based_taxonomy_archives_where', array( $this, 'filter_date_based_taxonomy_archives_where' ), 10, 2 );
+		add_filter( 'date_based_taxonomy_archives_join', array( $this, 'filter_date_based_taxonomy_archives_join' ), 10, 2 );
+		add_filter( 'get_archives_link', array( $this, 'filter_get_archives_link' ) );
+
+		add_action( 'generate_rewrite_rules', array( $this, 'action_generate_rewrite_rules' ) );
+	}
+
+	/**
+	 * Render unordered lists of monthly archive links grouped by year
+	 *
+	 * @param array $args
+	 * @uses $wpdb, $wp_locale, apply_filters, wp_parse_args, absint, this::get_incrementor, wp_cache_get, wp_cache_set, get_month_link, get_archives_link
+	 * @return string or false
+	 */
+	function get_archives( $args = array() ) {
+		global $wpdb, $wp_locale;
+
+		$args = apply_filters( 'date_based_taxonomy_archives_args', $args );
+		$args = wp_parse_args( $args, $this->defaults );
+		extract( $args );
+
+		//Build query
+		$where = apply_filters( 'date_based_taxonomy_archives_where', "WHERE post_type = 'post' AND post_status = 'publish'", $args );
+		$join = apply_filters( 'date_based_taxonomy_archives_join', '', $args );
+
+		if( is_numeric( $limit ) )
+			$limit = ' LIMIT ' . absint( $limit );
+
+		$query = $wpdb->prepare( "SELECT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC $limit" );
+
+		//Generate cache key, check cache, query DB if necessary and cache results
+		$cache_key = $this->get_incrementor() . md5( $query );
+
+		if( !$results = wp_cache_get( $cache_key, $this->cache_group ) ) {
+			$results = $wpdb->get_results( $query );
+
+			wp_cache_set( $cache_key, $results, $this->cache_group );
+		}
+
+		//Bail out if necessary data isn't available
+		if( !is_array( $results ) || empty( $results ) )
+			return false;
+
+		//Render archive
+		$output = '<ul>';
+		$cy = false;
+
+		//Alias $after for use inside of foreach
+		$_after = $after;
+
+		foreach( $results as $result ) {
+			if( $cy !== false && $cy != $result->year )
+				$output .= '</ul></li>';
+
+			if( $cy === false || $cy != $result->year ) {
+				$cy = $result->year;
+
+				$output .= '<li><span>' . absint( $result->year ) . '</span>';
+				$output .= '<ul>';
+			}
+
+			$url = get_month_link( $result->year, $result->month );
+
+			$text = $wp_locale->get_month( $result->month );
+
+			$after = $show_post_count ? '&nbsp;(' . absint( $result->posts ) . ')' . $_after : $_after;
+
+			$output .= get_archives_link( $url, $text, 'html', $before, $after );
+		}
+
+		if( $cy == $result->year )
+			$output .= '</ul></li>';
+
+		$output .= '</ul>';
+
+		//Reset archive links filter indicator
+		$this->filter_archive_links = false;
+
+		if( $echo )
+			echo $output;
+		else
+			return $output;
+	}
+
+	/**
+	 * Filter where clause used in this::get_archives
+	 *
+	 * @param string $where
+	 * @param array $args
+	 * @uses $wpdb, apply_filters, wp_parse_args, is_category, is_tag, is_tax, get_queried_object
+	 * @filter date_based_taxonomy_archives_where
+	 * @return string
+	 */
+	function filter_date_based_taxonomy_archives_where( $where, $args ) {
+		global $wpdb;
+
+		$args = apply_filters( 'date_based_taxonomy_archives_args', $args );
+		$args = wp_parse_args( $args, $this->defaults );
+		extract( $args );
+
+		if(
+			( $taxonomies == 'all' && ( is_category() || is_tag() || is_tax() ) ) ||
+			( $taxonomies == 'custom' && !is_category() && !is_tag() && is_tax() )
+		) {
+			$queried_object = get_queried_object();
+
+			if( is_object( $queried_object ) && property_exists( $queried_object, 'term_taxonomy_id' ) )
+				$where .= $wpdb->prepare( ' AND dbtrtr.term_taxonomy_id = %d', $queried_object->term_taxonomy_id );
+		}
+		elseif( is_array( $taxonomies ) ) {
+			$queried_object = get_queried_object();
+
+			if( is_object( $queried_object ) && property_exists( $queried_object, 'term_taxonomy_id' ) && property_exists( $queried_object, 'taxonomy' ) && in_array( $queried_object->taxonomy, $taxonomies ) )
+				$where .= $wpdb->prepare( ' AND dbtrtr.term_taxonomy_id = %d', $queried_object->term_taxonomy_id );
+		}
+
+		return $where;
+	}
+
+	/**
+	 * Filter join clause used in this::get_archives
+	 *
+	 * @param string $join
+	 * @param array $args
+	 * @uses $wpdb, apply_filters, wp_parse_args, is_category, is_tag, is_tax
+	 * @filter date_based_taxonomy_archives_join
+	 * @return string
+	 */
+	function filter_date_based_taxonomy_archives_join( $join, $args ) {
+		global $wpdb;
+
+		$args = apply_filters( 'date_based_taxonomy_archives_args', $args );
+		$args = wp_parse_args( $args, $this->defaults );
+		extract( $args );
+
+		if(
+			( $taxonomies == 'all' && ( is_category() || is_tag() || is_tax() ) ) ||
+			( $taxonomies == 'custom' && !is_category() && !is_tag() && is_tax() ) ||
+			is_array( $taxonomies )
+		) {
+			$join .= $wpdb->prepare( " INNER JOIN {$wpdb->term_relationships} AS dbtrtr on dbtrtr.object_id = {$wpdb->posts}.ID" );
+
+			$this->filter_archive_links = true;
+		}
+
+		return $join;
+	}
+
+	/**
+	 * Filter get_archives_link output to inject taxonomy and term slugs
+	 *
+	 * @param string $link_html
+	 * @uses $wp_rewrite, get_queried_object, is_wp_error, path_join, trailingslashit, home_url, get_taxonomy, add_query_arg
+	 * @filter get_archives_link
+	 * @return string
+	 */
+	function filter_get_archives_link( $link_html ) {
+		if( $this->filter_archive_links ) {
+			global $wp_rewrite;
+
+			$queried_object = get_queried_object();
+
+			if( is_object( $queried_object ) && !is_wp_error( $queried_object ) ) {
+				$exploded = explode( "'", $link_html );
+
+				if( $wp_rewrite->using_permalinks() && array_key_exists( $queried_object->taxonomy, $wp_rewrite->extra_permastructs ) ) {
+					$term_rewrite = preg_replace( '#%[^%]+%#i', $queried_object->slug, $wp_rewrite->extra_permastructs[ $queried_object->taxonomy ][ 0 ] );
+					$term_rewrite = substr( $term_rewrite, 1 ); //Drop leading slash, otherwise path_join misinterprets request
+					$term_rewrite = path_join( $term_rewrite, 'date' );
+
+					$exploded[ 1 ] = str_replace( trailingslashit( home_url() ), trailingslashit( path_join( home_url(), $term_rewrite ) ), $exploded[ 1 ] );
+				}
+				else {
+					$taxonomy = get_taxonomy( $queried_object->taxonomy );
+
+					if( is_object( $taxonomy ) && !is_wp_error( $taxonomy ) )
+						$exploded[ 1 ] = add_query_arg( $taxonomy->query_var, $queried_object->slug, $exploded[ 1 ] );
+				}
+
+				$link_html = implode( "'", $exploded );
+			}
+		}
+
+		return $link_html;
+	}
+
+	/**
+	 * Add rewrite rules to support [taxonomy]/[term]/date/[year]/[month]/page/[number]
+	 *
+	 * @param object $wp_rewrite
+	 * @uses get_taxonomies
+	 * @action generate_rewrite_rules
+	 * @return null
+	 */
+	function action_generate_rewrite_rules( $wp_rewrite ) {
+		$taxonomies = get_taxonomies( null, 'objects' );
+
+		if( is_array( $taxonomies ) && !empty( $taxonomies ) ) {
+			$rules = array();
+
+			foreach( $taxonomies as $taxonomy )
+				$rules[ $taxonomy->rewrite[ 'slug' ] . '/(.+?)/date/([0-9]{4})/([0-9]{1,2})/?(page/?([0-9]{1,})/?)?$' ] = 'index.php?' . $taxonomy->query_var . '=$matches[1]&year=$matches[2]&monthnum=$matches[3]&paged=$matches[5]';
+
+			$wp_rewrite->rules = $rules + $wp_rewrite->rules;
+		}
+	}
+
+	/**
+	 * Return cache incrementor. To invalidate caches, incrementor is deleted via this::action_transition_post_status.
+	 *
+	 * @uses wp_cache_get, wp_cache_set
+	 * @return int
+	 */
+	function get_incrementor() {
+		$incrementor = wp_cache_get( $this->cache_key_incrementor, $this->cache_group );
+
+		if( !is_numeric( $incrementor ) ) {
+			$incrementor = time();
+			wp_cache_set( $this->cache_key_incrementor, $incrementor, $this->cache_group );
+		}
+
+		return (int)$incrementor;
+	}
+
+	/**
+	 * Invalidate caches when posts are published or published posts are updated
+	 *
+	 * @param string $new_status
+	 * @param string $old_status
+	 * @uses wp_cache_delete
+	 * @action transition_post_status
+	 * @return null
+	 */
+	function action_transition_post_status( $new_status, $old_status ) {
+		if( $new_status == 'publish' || $old_status == 'publish' )
+			wp_cache_delete( $this->cache_key_incrementor, $this->cache_group );
+	}
+}
+global $date_based_taxonomy_archives;
+if( !is_a( $date_based_taxonomy_archives, 'Date_Based_Taxonomy_Archives' ) )
+	$date_based_taxonomy_archives = new Date_Based_Taxonomy_Archives;
+
+/**
+ * Render unordered lists of monthly archive links grouped by year
+ *
+ * @param array $args
+ * @uses $date_based_taxonomy_archives
+ * @return string or false
+ */
+function date_based_taxonomy_archives( $args = array() ) {
+	global $date_based_taxonomy_archives;
+	if( !is_a( $date_based_taxonomy_archives, 'Date_Based_Taxonomy_Archives' ) )
+		$date_based_taxonomy_archives = new Date_Based_Taxonomy_Archives;
+
+	return $date_based_taxonomy_archives->get_archives( $args );
+}
+?>
\ No newline at end of file
-- 
GitLab