<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/* <WP plugin data>
 * Plugin Name:   Custom Query String
 * Version:       2.2
 * Plugin URI:    http://mattread.com/archives/2005/03/custom-query-string-plugin/
 * Description:   Change the number of posts displayed when viewing an archive page.
 * Author:        Matt Read
 * Author URI:    http://www.mattread.com/
 *
 * License:       LGPL license 2.1
 *                http://www.gnu.org/copyleft/lesser.html
 */

define('k_CQS_VER', 2.2);

class cqs_core
{
	var $query = false;
	var $category = false;
	var $query_vars = array();
	var $query_string;
	var $options = array();
	var $option = array();

	/**
	 * Initializes the variables etc..
	 * @param string  the query string to be modified.
	 * @since version 2.0.1
	 */
	function init($query_string)
	{
		parse_str($query_string, $qv);
		$this->query_string = $query_string;
		$this->query_vars = $qv;
		$this->options = get_option('cqs_options');
		if ($this->options)
		{
			$this->get_query();
			$this->get_category();
		}
	}


	/**
	 * The main function, merges query string with our new queries
	 * @param string  the query string to be modified.
	 * @since version 2.0
	 * @return string  the new customized query string.
	 * @access public
	 */
	function custom_query_string($query_string) 
	{
		$this->init($query_string);
	
		/*
		 * Check if have a custom query for this category then check
		 * if have a custom query and only add it if it exsists.
		 */
		if ( $this->category )
			$this->option = $this->options[$this->category];
		elseif ( $this->query )
			$this->option = $this->options[$this->query];

		if ( $this->option )
		{
			$custom_query_string = array(
				'posts_per_page' => $this->option['posts_per_page'],
				'what_to_show' => $this->option['what_to_show'],
				'orderby' => $this->option['orderby'],
				'order' => $this->option['order']
				);
			/*
			 * Make sure we don't override any queries already set.  Merge
			 * the original query vars to the new ones.  Then build the string
			 * from the new array.
			 */
			$this->query_vars = array_merge($custom_query_string,$this->query_vars);
			$this->build_query_string();
		}
		return $this->query_string;
	}


	/**
	 * Rebuild query string from assosiative array
	 * @since version 2.0
	 */
	function build_query_string ()
	{
		foreach ($this->query_vars as $key => $value) {
			$query[] = $key.'='.$value;
		}
		$this->query_string = join('&', $query);
	}


	/**
	 * Determines the type of query to use
	 * the order is very important!
	 * archive includes: author, category and date.
	 * date includes: time, day, month, year.
	 * paged overrides all. Use with caution!
	 * @since version 2.0
	 */
	function get_query ()
	{
		global $wp_query;
		$wp_query->parse_query($this->query_string);

		if ($wp_query->is_feed AND $this->options['is_feed'])
			$this->query = 'is_feed';

		elseif ($wp_query->is_paged AND $this->options['is_paged'])
			$this->query = 'is_paged';

		elseif ($wp_query->is_archive)
		{
			if ($wp_query->is_author AND $this->options['is_author'])
				$this->query = 'is_author';

			elseif ($wp_query->is_category AND $this->options['is_category'])
				$this->query = 'is_category';
			
			elseif ($wp_query->is_date)
			{
				if ($wp_query->is_time AND $this->options['is_time'])
					$this->query = 'is_time';
				
				elseif ($wp_query->is_day AND $this->options['is_day'])
					$this->query = 'is_day';
				
				elseif ($wp_query->is_month AND $this->options['is_month'])
					$this->query = 'is_month';
				
				elseif ($wp_query->is_year AND $this->options['is_year'])
					$this->query = 'is_year';
				
				elseif ($this->options['is_date'])
					$this->query = 'is_date';
			}
			elseif ($this->options['is_archive'])
				$this->query = 'is_archive';
		}
		elseif ($wp_query->is_search AND $this->options['is_search'])
			$this->query = 'is_search';

		elseif ($wp_query->is_home AND $this->options['is_home'])
			$this->query = 'is_home';

		else 
			$this->query = false;
	}

	/**
	 * Get the category ID
	 * @since version 2.2
	 */
	function get_category ()
	{
		global $wp_query;
		if ( $wp_query->is_category )
		{
			if ( !($category = $wp_query->get('cat')) )
			{
				$category = $wp_query->get('category_name');
				$category = $this->get_category_id($category);
			}
			if ( $this->options['cat_'.$category] )
				$this->category = 'cat_'.$category;
		}
	}

	/**
	 * Get the category ID from category nice_name.
	 * @since version 2.2
	 * @param string  The category nice_name.
	 * @return int  The category id.
	 */
	function get_category_id($category_name)
	{
		global $wpdb;
		return $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE category_nicename = '" . $category_name . "'");
	}
}


class cqs_options_page extends cqs_core
{

	var $what_to_shows = array('posts', 'days');
	var $conditions = array('is_archive', 'is_author', 'is_category', 'is_date', 'is_year', 'is_month', 'is_day', 'is_time', 'is_search', 'is_home', 'is_paged', 'is_feed');
	var $orderbys = array('date','category','title','author');
	var $orders = array('DESC', 'ASC');
	var $request = array();


	/**
	 * initializes the options page
	 * @since version 2.0
	 */
	function options_page ()
	{
		$this->options = get_option('cqs_options');
		$this->request = $_REQUEST['cqs'];

		if ($this->request['submit'] == 'Delete All')
		{
			delete_option('cqs_options');
			$this->options = array();
			$this->display_options_page('delete');
		}
		elseif ( $this->request['submit'] == 'Add' OR $this->request['category']['submit'] == 'Add' )
		{
			$this->add_options();
			$this->display_options_page('update');
		}
		elseif ($this->request['submit'] == 'Delete Checked')
		{
			$this->delete_options();
			$this->display_options_page('update');
		}
		else
		{
			$this->display_options_page();
		}
		$this->footer();
	}


	/**
	 * adds/updates new options
	 * @since version 2.0
	 */
	function add_options ()
	{
		if ( $this->request['category']['submit'] )
		{
			$cqs_new_options = array(
				'cat_'. $_REQUEST['cat'] => array(
					'posts_per_page' => $this->request['category']['posts_per_page'],
					'what_to_show' => $this->request['category']['what_to_show'],
					'orderby' => $this->request['category']['orderby'],
					'order' => $this->request['category']['order']
				));
		}
		else
		{
			$cqs_new_options = array(
				$this->request['condition'] => array(
					'posts_per_page' => $this->request['posts_per_page'],
					'what_to_show' => $this->request['what_to_show'],
					'orderby' => $this->request['orderby'],
					'order' => $this->request['order']
				));
		}

		if ($this->options)
			$this->options = array_merge($this->options, $cqs_new_options);

		else
			$this->options = $cqs_new_options;

		add_option('cqs_options', false);
		update_option('cqs_options', $this->options);
	}


	/**
	 * deletes selected options
	 * @since version 2.0
	 */
	function delete_options ()
	{
		if ($this->request['delete'])
		{
			foreach( $this->request['delete'] as $delete )
				unset($this->options[$delete]);
		}
		add_option('cqs_options', false);
		update_option('cqs_options', $this->options);
	}


	/**
	 * Display the footer with Credit.
	 * @since version 2.2
	 */
	function footer()
	{
		echo '<div class="wrap" style="text-align:center;">Custom Query String v'. k_CQS_VER .' by <a href="http://mattread.com">Matt Read</a>.</div>';
	}


	/**
	 * display the options page
	 * @param string Which update message to show. Either 'updated' or 'delete'.
	 * @since version 2.0
	 */
	function display_options_page ($updated = false)
	{
		if ($updated == 'update')
		{ 
			echo "<div class=\"updated\">
			<p>Your options have been <strong>Updated</strong>.</p>
			</div>";
		}
	
		if ($updated == 'delete')
		{
			echo "<div class=\"updated\">
			<p>CQS has been Succesfully <strong>Deleted</strong>. You can deactivate the plugin now.</p>
			</div>";
		}
	
	// now do the display
	?>
	<form name="cqsoptions" method="post">
	<?php if ($this->options) { ?>
	<div class="wrap"><h2>Current Conditions</h2>
	
		<table cellspacing="2" cellpadding="5" width="80%">
		<tr class="alternate">
		<th></th>
		<th>Condition</th>
		<th>Result</th>
		</tr>
	
		<?php
		$i = 0;
		foreach ($this->options as $condition => $cqs_option) { ?>
		<tr valign="top" <?php if ($i % 2 != 0) echo 'class="alternate"'; ?>>
			<td><input type="checkbox" name="cqs[delete][]" value="<?php echo $condition; ?>" /></td>
			<td><strong><?php echo $condition; ?></strong></td>
			<td>show <?php echo $cqs_option['posts_per_page']; ?> <?php echo $cqs_option['what_to_show']; ?> per page, ordered by <?php echo $cqs_option['orderby']; ?> <?php echo $cqs_option['order']; ?></td>
		</tr>
		<?php $i++; } ?>
		</table>
	
		<p>
		<input type="submit" name="cqs[submit]" value="Delete Checked" />
		</p>
		<p class="submit">
		<input type="submit" name="cqs[submit]" value="Delete All">
		</p>
	</div>
	<?php } ?>
	
	<div class="wrap"><h2>Add New Condition</h2>
		<p>To update current conditions replace them with new ones here. Use '-1' to show all posts.</p>
		
		<fieldset>
		<legend>New Condition</legend>
		<p>
			if
			<select name="cqs[condition]">
			<?php 
			foreach ($this->conditions as $condition) {
				echo "<option>$condition</option>";
			}
			?>
			</select>
	
			show <input type="text" name="cqs[posts_per_page]" size="3" />
	
			<select name="cqs[what_to_show]">
			<?php 
			foreach ($this->what_to_shows as $what_to_show) {
				echo "<option>$what_to_show</option>";
			}
			?>
			</select> per page, 
	
			ordered by
			<select name="cqs[orderby]">
			<?php 
			foreach ($this->orderbys as $orderby) {
				echo "<option>$orderby</option>";
			}
			?>
			</select> 
			<select name="cqs[order]">
			<?php 
			foreach ($this->orders as $order) {
				echo "<option>$order</option>";
			}
			?>
			</select>
	
			&nbsp;&nbsp;
			<input type="submit" name="cqs[submit]" value="Add" />
		</p>
		</fieldset>

		<fieldset>
		<legend>New Category Condition</legend>
		<p>
			if is category			
			<?php dropdown_cats($optionall = 0, $all = 'All', $sort_column = 'ID', $sort_order = 'asc', $optiondates = 0, $optioncount = 0, $hide_empty = 0, $optionnone=FALSE, $selected=0, $hide=0) ?>
	
			show <input type="text" name="cqs[category][posts_per_page]" size="3" />
	
			<select name="cqs[category][what_to_show]">
			<?php 
			foreach ($this->what_to_shows as $what_to_show) {
				echo "<option>$what_to_show</option>";
			}
			?>
			</select> per page, 
	
			ordered by
			<select name="cqs[category][orderby]">
			<?php 
			foreach ($this->orderbys as $orderby) {
				echo "<option>$orderby</option>";
			}
			?>
			</select> 
			<select name="cqs[category][order]">
			<?php 
			foreach ($this->orders as $order) {
				echo "<option>$order</option>";
			}
			?>
			</select>
	
			&nbsp;&nbsp;
			<input type="submit" name="cqs[category][submit]" value="Add" />
		</p>
		</fieldset>
	</div>
	
	</form>
	<?php
	}
}


/*
 * Start the options page.
 */
function cqs_options_init()
{
	$cqs = new cqs_options_page;
	$cqs->options_page();
}

/*
 * Start cqs. return the new modified query string.
 */
function cqs_init($query_string)
{
	$cqs = new cqs_core;
	$query_string = $cqs->custom_query_string($query_string);
	return $query_string;
}

/*
 * Add options page link to admin menu.
 * Only accessible by user_level of 9 or greater.
 */
function cqs_options()
{
	add_options_page('CQS Options', 'CQS', 9, basename(__FILE__), 'cqs_options_init');
}

add_action('admin_menu', 'cqs_options');
add_filter('query_string', 'cqs_init');


?>