<?php
/**
 * This program is licenced under the The GNU General Public License (GPL).
 *
 * Copyright (C) Kjetil Hårtveit 2010
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 * License for more details.
 * @license http://www.opensource.org/licenses/gpl-license.html
 *
 *---------------------------------------
 *
 * Makes pages overview out of a collection of items.
 *
 * Future ideas:
 * @todo add truncation
 * @todo add customizeable page values? Instead of 1 2 3, make it possible with A B C?
 *
 * @author Kjetil Hårtveit <kjetil@kjetil-hartveit.com> http://www.kjetil-hartveit.com
 * @version 1.0
 */
class PageLister
{
	protected $allItems = array();
	protected $page = 1;
	protected $pageList = array();

	/**
	 * Default options
	 *
	 * @var array
	 */
	protected $opts = array(
		'itemsPerPage' => 5,
		'urlFormat'		 => '%d',
		'pageLabels'	 => array(),
		'prevAndNext'	 => true,
		'prev'				=> '«',
		'next'				=> '»'
	);

	/**
	 * <h3>Possible options:</h3>
	 * <table>
	 *	 <tr>
	 *		<th>Type</th>
	 *		<th>Option</th>
	 *		<th>Default</th>
	 *		<th>Description</th>
	 *	 </tr>
	 *	 <tr>
	 *		 <td>string</td>
	 *		 <td>itemsPerPage</td>
	 *     <td>5</td>
	 *     <td>Number of items shown per page</td>
	 *   </tr>
	 *   <tr>
	 *     <td>string</td>
	 *     <td>urlFormat</td>
	 *     <td>%d</td>
	 *     <td>Here you can choose the format of the url. The only required argument is %d (the page number)</td>
   *   </tr>
	 *   <tr>
	 *     <td>array</td>
	 *     <td>pageLabels</td>
	 *     <td>array()</td>
	 *     <td>Each individual page can be given a specific page label with this option. Each key in the array is the pagenumber and the value is the page label.</td>
   *   </tr>
	 *   <tr>
	 *     <td>boolean</td>
	 *     <td>prevAndNext</td>
	 *     <td>true</td>
	 *     <td>Whether or not to include the "previous" and "next" items in the page list</td>
   *   </tr>
	 *   <tr>
	 *     <td>string</td>
	 *     <td>prev</td>
	 *     <td>«</td>
	 *     <td>The text shown as "previous page"</td>
   *   </tr>
	 *   <tr>
	 *     <td>string</td>
	 *     <td>next</td>
	 *     <td>»</td>
	 *     <td>The text shown as "next page"</td>
   *   </tr>
	 * </table>
	 *
	 * @param array $allItems All of the items which you want to generate a pagelist from
	 * @param int $page Current page
	 * @param array $opts array with options given as key-value pair.
	 */
	function __construct($allItems, $page, $opts=array())
	{
		$this->setAllItems($allItems);
		$this->setPage($page);
		$this->setOpts(array_merge($this->getOpts(), $opts));
	}

	/**
	 * Makes page overview
	 *
	 * <p>The page list is an associative array consisting of the following key pairs:</p>
	 * <table>
	 *   <tr>
	 *	   <th>Type</th>
	 *	   <th>Key</th>
	 *	   <th>Value</th>
	 *   </tr>
	 *	 <tr>
	 *		 <td>string</td>
	 *		 <td>url</td>
	 *		 <td>The formatted url for the page. Note that when using the 'prevAndNext' option and
				there is no valid previous or next page, then the url will be null. This is also the case
				if a pagelink points to the current page. You can use this info to remove links that the
				user should not click on.</td>
	 *   </tr>
	 *	 <tr>
	 *		 <td>int</td>
	 *		 <td>page</td>
	 *		 <td>The pagenumber</td>
	 *   </tr>
	 *	 <tr>
	 *		 <td>string</td>
	 *		 <td>label</td>
	 *		 <td>The page label</td>
	 *   </tr>
	 * </table>
	 *
	 * @return array Page list
	 */
	function makePageList()
	{
		$page = $this->getPage();
		$allItems = $this->getAllItems();
		$urlFormat = $this->getOpt('urlFormat');
		$prevAndNext = $this->getOpt('prevAndNext');
		$pageLabels = $this->getOpt('pageLabels');
		$itemsPerPage = $this->getOpt('itemsPerPage');

		$numPages = ceil(count($allItems)/$itemsPerPage);

		$pageList = array();

		$prev = $page-1;
		$next = $page+1;
		$prevUrl = $prev>0 ? sprintf($urlFormat, $prev) : null;
		$nextUrl = $next<=$numPages ? sprintf($urlFormat, $next) : null;

			if ($prevAndNext)
			{
				$pageList[] = array(
					'page'  => $prev,
					'url'	  => $prevUrl,
					'label' => $this->getOpt('prev')
				);
			}

			for ($i=1; $i<=$numPages; $i++)
			{
				$curUrl = $page!=$i ? sprintf($urlFormat, $i) : null;
				$pageList[] = array(
					'page'  => $i,
					'url'	  => $curUrl,
					'label' => isset($pageLabels[$i]) ? $pageLabels[$i] : $i
				);
			}

			if ($prevAndNext)
			{
				$pageList[] = array(
					'page'  => $next,
					'url'	  => $nextUrl,
					'label' => $this->getOpt('next')
				);
			}

		$this->setPageList($pageList);
		return $pageList;
	}

	/**
	 * Returns current items
	 *
	 * @return array
	 */
	function getCurrentItems()
	{
		$allItems = $this->getAllItems();
		$page = $this->getPage();
		$itemsPerPage = $this->getOpt('itemsPerPage');

		return array_slice($allItems, ($page-1)*$itemsPerPage, $itemsPerPage);
	}

	/**
	 * Returns a single option
	 *
	 * @param string $opt
	 * @return mixed
	 */
	function getOpt($opt)
	{
		$opts = $this->getOpts();
			if (isset($opts[$opt]))
			{
				return $opts[$opt];
			}
		return null;
	}

	function setAllItems($allItems) { $this->allItems = $allItems; }
	function getAllItems() { return $this->allItems; }
	function setPage($page) { $this->page = $page; }
	function getPage() { return $this->page; }
	function setOpts($opts) { $this->opts = $opts; }
	function getOpts() { return $this->opts; }
	function setPageList($pageList) { $this->pageList = $pageList; }
	function getPageList() { return $this->pageList; }
}
?>