This commit is contained in:
Deon George 2011-08-27 17:14:02 +10:00
parent 2d02bde964
commit ee0cc6aac5
13 changed files with 607 additions and 0 deletions

View File

@ -111,6 +111,7 @@ Kohana::modules(array(
'userguide' => SMDPATH.'userguide', // User guide and API documentation 'userguide' => SMDPATH.'userguide', // User guide and API documentation
'khemail' => SMDPATH.'khemail', // Email module for Kohana 3 PHP Framework 'khemail' => SMDPATH.'khemail', // Email module for Kohana 3 PHP Framework
'gchart' => MODPATH.'gchart', // Google Chart Module 'gchart' => MODPATH.'gchart', // Google Chart Module
'pagination' => SMDPATH.'pagination', // Kohana Pagination module for Kohana 3 PHP Framework
'xml' => SMDPATH.'xml', // XML module for Kohana 3 PHP Framework 'xml' => SMDPATH.'xml', // XML module for Kohana 3 PHP Framework
)); ));

View File

@ -0,0 +1 @@
.DS_Store

View File

@ -0,0 +1,335 @@
<?php defined('SYSPATH') or die('No direct script access.');
/**
* Pagination links generator.
*
* @package Kohana/Pagination
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license.html
*
* @method Pagination current_page()
* @method Pagination total_items()
* @method Pagination items_per_page()
* @method Pagination total_pages()
* @method Pagination current_first_item()
* @method Pagination current_last_item()
* @method Pagination previous_page()
* @method Pagination next_page()
* @method Pagination first_page()
* @method Pagination last_page()
* @method Pagination offset()
*/
class Kohana_Pagination {
/**
* @var array Merged configuration settings
*/
protected $config = array(
'current_page' => array('source' => 'query_string', 'key' => 'page'),
'total_items' => 0,
'items_per_page' => 10,
'view' => 'pagination/basic',
'auto_hide' => TRUE,
'first_page_in_url' => FALSE,
);
/**
* @var array Members that have access methods
*/
protected $_properties = array(
'current_page', 'total_items', 'items_per_page', 'total_pages', 'current_first_item', 'current_last_item',
'previous_page', 'next_page', 'first_page', 'last_page', 'offset',
);
// Current page number
protected $_current_page;
// Total item count
protected $_total_items;
// How many items to show per page
protected $_items_per_page;
// Total page count
protected $_total_pages;
// Item offset for the first item displayed on the current page
protected $_current_first_item;
// Item offset for the last item displayed on the current page
protected $_current_last_item;
// Previous page number; FALSE if the current page is the first one
protected $_previous_page;
// Next page number; FALSE if the current page is the last one
protected $_next_page;
// First page number; FALSE if the current page is the first one
protected $_first_page;
// Last page number; FALSE if the current page is the last one
protected $_last_page;
// Query offset
protected $_offset;
/**
* Creates a new Pagination object.
*
* @param array configuration
* @return Pagination
*/
public static function factory(array $config = array())
{
return new Pagination($config);
}
/**
* Creates a new Pagination object.
*
* @param array configuration
* @return void
*/
public function __construct(array $config = array())
{
// Overwrite system defaults with application defaults
$this->config = $this->config_group() + $this->config;
// Pagination setup
$this->setup($config);
}
/**
* Retrieves a pagination config group from the config file. One config group can
* refer to another as its parent, which will be recursively loaded.
*
* @param string pagination config group; "default" if none given
* @return array config settings
*/
public function config_group($group = 'default')
{
// Load the pagination config file
$config_file = Kohana::config('pagination');
// Initialize the $config array
$config['group'] = (string) $group;
// Recursively load requested config groups
while (isset($config['group']) AND isset($config_file->$config['group']))
{
// Temporarily store config group name
$group = $config['group'];
unset($config['group']);
// Add config group values, not overwriting existing keys
$config += $config_file->$group;
}
// Get rid of possible stray config group names
unset($config['group']);
// Return the merged config group settings
return $config;
}
/**
* Loads configuration settings into the object and (re)calculates pagination if needed.
* Allows you to update config settings after a Pagination object has been constructed.
*
* @param array configuration
* @return object Pagination
*/
public function setup(array $config = array())
{
if (isset($config['group']))
{
// Recursively load requested config groups
$config += $this->config_group($config['group']);
}
// Overwrite the current config settings
$this->config = $config + $this->config;
// Only (re)calculate pagination when needed
if ($this->_current_page === NULL
OR isset($config['current_page'])
OR isset($config['total_items'])
OR isset($config['items_per_page']))
{
// Retrieve the current page number
if ( ! empty($this->config['current_page']['page']))
{
// The current page number has been set manually
$this->_current_page = (int) $this->config['current_page']['page'];
}
else
{
switch ($this->config['current_page']['source'])
{
case 'query_string':
$this->_current_page = isset($_GET[$this->config['current_page']['key']])
? (int) $_GET[$this->config['current_page']['key']]
: 1;
break;
case 'route':
$this->_current_page = (int) Request::current()->param($this->config['current_page']['key'], 1);
break;
}
}
// Calculate and clean all pagination variables
$this->_total_items = (int) max(0, $this->config['total_items']);
$this->_items_per_page = (int) max(1, $this->config['items_per_page']);
$this->_total_pages = (int) ceil($this->_total_items / $this->_items_per_page);
$this->_current_page = (int) min(max(1, $this->_current_page), max(1, $this->_total_pages));
$this->_current_first_item = (int) min((($this->_current_page - 1) * $this->_items_per_page) + 1, $this->_total_items);
$this->_current_last_item = (int) min($this->_current_first_item + $this->_items_per_page - 1, $this->_total_items);
$this->_previous_page = ($this->_current_page > 1) ? $this->_current_page - 1 : FALSE;
$this->_next_page = ($this->_current_page < $this->_total_pages) ? $this->_current_page + 1 : FALSE;
$this->_first_page = ($this->_current_page === 1) ? FALSE : 1;
$this->_last_page = ($this->_current_page >= $this->_total_pages) ? FALSE : $this->_total_pages;
$this->_offset = (int) (($this->_current_page - 1) * $this->_items_per_page);
}
// Chainable method
return $this;
}
/**
* Generates the full URL for a certain page.
*
* @param integer page number
* @return string page URL
*/
public function url($page = 1)
{
// Clean the page number
$page = max(1, (int) $page);
// No page number in URLs to first page
if ($page === 1 AND ! $this->config['first_page_in_url'])
{
$page = NULL;
}
switch ($this->config['current_page']['source'])
{
case 'query_string':
return URL::site(Request::current()->uri()).URL::query(array($this->config['current_page']['key'] => $page));
case 'route':
return URL::site(Request::current()->uri(array($this->config['current_page']['key'] => $page))).URL::query();
}
return '#';
}
/**
* Checks whether the given page number exists.
*
* @param integer page number
* @return boolean
* @since 3.0.7
*/
public function valid_page($page)
{
// Page number has to be a clean integer
if ( ! Valid::digit($page))
return FALSE;
return $page > 0 AND $page <= $this->_total_pages;
}
/**
* Renders the pagination links.
*
* @param mixed string of the view to use, or a Kohana_View object
* @return string pagination output (HTML)
*/
public function render($view = NULL)
{
// Automatically hide pagination whenever it is superfluous
if ($this->config['auto_hide'] === TRUE AND $this->_total_pages <= 1)
return '';
if ($view === NULL)
{
// Use the view from config
$view = $this->config['view'];
}
if ( ! $view instanceof View)
{
// Load the view file
$view = View::factory($view);
}
// Pass on the whole Pagination object
return $view->set(get_object_vars($this))->set('page', $this)->render();
}
/**
* Renders the pagination links.
*
* @return string pagination output (HTML)
*/
public function __toString()
{
try
{
return $this->render();
}
catch(Exception $e)
{
Kohana_Exception::handler($e);
return '';
}
}
/**
* Handles loading and setting properties.
*
* @param string $method Method name
* @param array $args Method arguments
* @return mixed
*/
public function __call($method, array $args)
{
if (in_array($method, $this->_properties))
{
if (!count($args))
{
return $this->{'_'.$method};
}
}
else
{
throw new Kohana_Exception('Invalid method :method called in :class',
array(':method' => $method, ':class' => get_class($this)));
}
}
/**
* Handles setting of property
*
* @param string $key Property name
* @param mixed $value Property value
* @return void
*/
public function __set($key, $value)
{
if (isset($this->{'_'.$key}))
{
$this->setup(array($key => $value));
}
else
{
throw new Kohana_Exception('The :property: property does not exist in the :class: class',
array(':property:' => $key, ':class:' => get_class($this)));
}
}
} // End Pagination

View File

@ -0,0 +1,3 @@
<?php defined('SYSPATH') or die('No direct script access.');
class Pagination extends Kohana_Pagination {}

View File

@ -0,0 +1,15 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array(
// Application defaults
'default' => array(
'current_page' => array('source' => 'query_string', 'key' => 'page'), // source: "query_string" or "route"
'total_items' => 0,
'items_per_page' => 10,
'view' => 'pagination/basic',
'auto_hide' => TRUE,
'first_page_in_url' => FALSE,
),
);

View File

@ -0,0 +1,23 @@
<?php defined('SYSPATH') or die('No direct script access.');
return array(
// Leave this alone
'modules' => array(
// This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
'pagination' => array(
// Whether this modules userguide pages should be shown
'enabled' => TRUE,
// The name that should show up on the userguide index page
'name' => 'Pagination',
// A short description of this module, shown on the index page
'description' => 'Tool for creating paginated links and viewing pages of results.',
// Copyright message, shown in the footer for this module
'copyright' => '&copy; 20082010 Kohana Team',
)
)
);

View File

@ -0,0 +1,94 @@
# Pagination Configuration
[Pagination] uses 6 settings: `current_page`, `total_items`, `items_per_page`, `view`, `auto_hide` and `first_page_in_url`.
## Configuration Examples
This example shows the default configuration:
return array(
// Application defaults
'default' => array(
'current_page' => array('source' => 'query_string', 'key' => 'page'), // source: "query_string" or "route"
'total_items' => 0,
'items_per_page' => 10,
'view' => 'pagination/basic',
'auto_hide' => TRUE,
'first_page_in_url' => FALSE,
),
);
This is an example with multiple configurations:
return array(
// Application defaults
'default' => array(
'current_page' => array('source' => 'query_string', 'key' => 'page'),
'total_items' => 0,
'items_per_page' => 10,
'view' => 'pagination/basic',
'auto_hide' => TRUE,
'first_page_in_url' => FALSE,
),
// Second configuration
'pretty' => array(
'current_page' => array('source' => 'route', 'key' => 'page'),
'total_items' => 0,
'items_per_page' => 20,
'view' => 'pagination/pretty',
'auto_hide' => TRUE,
'first_page_in_url' => FALSE,
),
);
## Settings
### current_page
The `current_page` setting tells Pagination where to look to find the current page number.
There are two options for the `source` of the page number: `query_string` and `route`.
The `key` index in the configuration array tells Pagination what name to look for when it's searching in the query string or route.
This configuration informs Pagination to look in the query string for a value named `page`:
'current_page' => array('source' => 'query_string', 'key' => 'page'),
If you have a route setup with the page number in the actual URL like this:
Route::set('city_listings', '<city>listings(/<page_num>)', array('page_num' => '[0-9]+'))
->defaults(array(
'controller' => 'city',
'action' => 'listings'
));
then you would use a setting like this:
'current_page' => array('source' => 'route', 'key' => 'page_num'),
### total_items
`total_items` is a setting you will most likely pass in during runtime after figuring out exactly how many items you have. It can be set to zero in the configuration for now.
### items_per_page
Self explanatory. This is the maximum items to show on each page. Pagination determines the total number of pages based off of this number.
### view
The `view` setting should be a path to a Pagination view file.
### auto_hide
If `auto_hide` is set to `TRUE` then Pagination will automatically hide whenever there's only one page of items.
### first_page_in_url
If you want Pagination to add the page number to the first page's link then set this setting to `TRUE` otherwise leave it as `FALSE`.

View File

@ -0,0 +1,4 @@
## [Pagination]()
- [Config](config)
- [Usage](usage)
- [Examples](examples)

View File

@ -0,0 +1,37 @@
<p class="pagination">
<?php if ($page->first_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->first_page())) ?>" rel="first"><?php echo __('First') ?></a>
<?php else: ?>
<?php echo __('First') ?>
<?php endif ?>
<?php if ($page->previous_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->previous_page())) ?>" rel="prev"><?php echo __('Previous') ?></a>
<?php else: ?>
<?php echo __('Previous') ?>
<?php endif ?>
<?php for ($i = 1; $i <= $page->total_pages(); $i++): ?>
<?php if ($i == $page->current_page()): ?>
<strong><?php echo $i ?></strong>
<?php else: ?>
<a href="<?php echo HTML::chars($page->url($i)) ?>"><?php echo $i ?></a>
<?php endif ?>
<?php endfor ?>
<?php if ($page->next_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->next_page())) ?>" rel="next"><?php echo __('Next') ?></a>
<?php else: ?>
<?php echo __('Next') ?>
<?php endif ?>
<?php if ($page->last_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->last_page())) ?>" rel="last"><?php echo __('Last') ?></a>
<?php else: ?>
<?php echo __('Last') ?>
<?php endif ?>
</p><!-- .pagination -->

View File

@ -0,0 +1,94 @@
<?php
/*
First Previous 1 2 3 ... 22 23 24 25 26 [27] 28 29 30 31 32 ... 48 49 50 Next Last
*/
// Number of page links in the begin and end of whole range
$count_out = ( ! empty($config['count_out'])) ? (int) $config['count_out'] : 3;
// Number of page links on each side of current page
$count_in = ( ! empty($config['count_in'])) ? (int) $config['count_in'] : 5;
// Beginning group of pages: $n1...$n2
$n1 = 1;
$n2 = min($count_out, $page->total_pages());
// Ending group of pages: $n7...$n8
$n7 = max(1, $page->total_pages() - $count_out + 1);
$n8 = $page->total_pages();
// Middle group of pages: $n4...$n5
$n4 = max($n2 + 1, $page->current_page() - $count_in);
$n5 = min($n7 - 1, $page->current_page() + $count_in);
$use_middle = ($n5 >= $n4);
// Point $n3 between $n2 and $n4
$n3 = (int) (($n2 + $n4) / 2);
$use_n3 = ($use_middle && (($n4 - $n2) > 1));
// Point $n6 between $n5 and $n7
$n6 = (int) (($n5 + $n7) / 2);
$use_n6 = ($use_middle && (($n7 - $n5) > 1));
// Links to display as array(page => content)
$links = array();
// Generate links data in accordance with calculated numbers
for ($i = $n1; $i <= $n2; $i++)
{
$links[$i] = $i;
}
if ($use_n3)
{
$links[$n3] = '&hellip;';
}
for ($i = $n4; $i <= $n5; $i++)
{
$links[$i] = $i;
}
if ($use_n6)
{
$links[$n6] = '&hellip;';
}
for ($i = $n7; $i <= $n8; $i++)
{
$links[$i] = $i;
}
?>
<p class="pagination">
<?php if ($page->first_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->first_page())) ?>" rel="first"><?php echo __('First') ?></a>
<?php else: ?>
<?php echo __('First') ?>
<?php endif ?>
<?php if ($page->previous_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->previous_page())) ?>" rel="prev"><?php echo __('Previous') ?></a>
<?php else: ?>
<?php echo __('Previous') ?>
<?php endif ?>
<?php foreach ($links as $number => $content): ?>
<?php if ($number === $page->current_page()): ?>
<strong><?php echo $content ?></strong>
<?php else: ?>
<a href="<?php echo HTML::chars($page->url($number)) ?>"><?php echo $content ?></a>
<?php endif ?>
<?php endforeach ?>
<?php if ($page->next_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->next_page())) ?>" rel="next"><?php echo __('Next') ?></a>
<?php else: ?>
<?php echo __('Next') ?>
<?php endif ?>
<?php if ($page->last_page() !== FALSE): ?>
<a href="<?php echo HTML::chars($page->url($page->last_page())) ?>" rel="last"><?php echo __('Last') ?></a>
<?php else: ?>
<?php echo __('Last') ?>
<?php endif ?>
</p><!-- .pagination -->