<?php
/*
Plugin Name: Offset Headings
Description: Shift HTML headings (<code>h1</code>, <code>h2</code>…) in posts depending on the query type.
Author: Sam
Version: 0.2
*/


if (function_exists('add_action')) {
	add_action('wp', 'ho_start');	
} else { // Testing
	$h = new HeadingOffsetter();
	$h->set_offset(2);
	echo $h->filter_headings('<h1>(1)Hello!</h1> <h5>(5)heading</h5> <h3 id="third">(3)heading</h3>');
}

function ho_start() {
	if ( ! isset($GLOBALS['HeadingOffsetter']) ) {
		$GLOBALS['HeadingOffsetter'] = new HeadingOffsetter();
		$GLOBALS['HeadingOffsetter']->offsets = apply_filters( 'ho_offsets', $GLOBALS['HeadingOffsetter']->offsets );
		$GLOBALS['HeadingOffsetter']->set_offset_by_query();
		$GLOBALS['HeadingOffsetter']->add_hooks();
	}
}

class HeadingOffsetter {
	##	Options
	
	/**
	 * The offset applied when none of the conditions below match
	 *
	 * @var integer
	 */
	var $default_offset = 0;
	// TODO: add a method to set these; apply_filter also
	// For finer control, use $HeadingOffsetter->set_offset($int) in your template
	/**
	 * array { (string) condition => (integer) offset, }
	 *
	 * @var array
	 */
	
	var $offsets = array(
		// condition => offset level
		'is_home' => 1,
		'is_feed' => 0,
		'is_page' => 2,
		'is_single' => 2,
		'is_archive' => 3,
		);
	var $priority = 7;
	
	##	Properties (private)
	var $offset = 0;
	var $replace = array();
	
	function &__construct() {
		return $this;
	}
	
	function HeadingOffsetter() {
		$this->__construct();
	}
	
	function add_hooks() {
		// After Markdown or other markup transformers
		add_filter('the_content', array(&$this, 'filter_headings'), apply_filters('ho_priority', $this->priority));
	}
	
	function set_offset($n) {
		$this->offset = (int) $n;
		$this->make_replace_array();
	}
	
	function get_offset() {
		return $this->offset;
	}
	
	function make_replace_array() {
		if ($this->offset > 0) {
			foreach ( range(1,6) as $i ) {
				$n = min(6, max($i + $this->offset, 1));
				$this->replace["<h$i"] = "<h$n";
				$this->replace["</h$i>"] = "</h$n>";
			}
		}
		return $this->replace;
	}
	
	function filter_headings($text) {
		if ( ! empty($this->replace) ) {
			$text = strtr($text, $this->replace);
		}
		return $text;
	}
	
	function set_offset_by_query() {
		// Choose offset level (from options) based on WP query type
		foreach ($this->offsets as $is_query_type => $n) {
			if ( true == call_user_func($is_query_type)) {
				// offset value NULL means use the default offset level
				$this->set_offset( isset($n) ? $n : $this->default_offset );
				return;
			}
		}
		// Otherwise use default
		$this->set_offset($this->default_offset);
	}
}

?>