Last active
August 17, 2016 07:55
-
-
Save anjan011/4c1a2a6068d189a6769a to your computer and use it in GitHub Desktop.
php class: SimplePager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Created by PhpStorm. | |
* User: anjan | |
* Date: 9/30/15 | |
* Time: 9:23 AM | |
*/ | |
class SimplePager { | |
const DEFAULT_RECORDS_PER_PAGE = 20; | |
const DEFAULT_MAX_VISIBLE_LINK = 3; | |
const DEFAULT_PAGE_NUMBER_TEMPLATE_TAG = '{{page}}'; | |
/** | |
* Total records | |
* | |
* @var int | |
*/ | |
private $totalRecords = 0; | |
/** | |
* Records per page | |
* | |
* @var int | |
*/ | |
private $recordsPerPage = self::DEFAULT_RECORDS_PER_PAGE; | |
/** | |
* Total pages (Calculated) | |
* | |
* @var int | |
*/ | |
private $totalPages = 0; | |
/** | |
* max visible links | |
* | |
* @var int | |
*/ | |
private $maxVisibleLinks = 5; | |
/** | |
* The base URL | |
* | |
* @var string | |
*/ | |
private $pageUrl = ''; | |
/** | |
* Page number template tag, which will be replaced by actual page number | |
* | |
* @var string | |
*/ | |
private $pageNumberTemplateTag = '{{page}}'; | |
/** | |
* Current page number | |
* | |
* @var int | |
*/ | |
private $currentPageNumber = 1; | |
/** | |
* Pager container tag | |
* | |
* @var array | |
*/ | |
private $pagerContainer = array( | |
'tag' => 'ul', | |
'attrs' => array( | |
'class' => 'pagination' | |
) | |
); | |
/** | |
* Each link container tag | |
* | |
* @var string | |
*/ | |
private $linkContainer = array( | |
'tag' => 'li', | |
'attrs' => array( | |
'class' => '' | |
) | |
); | |
/** | |
* Common css class for page hyperlinks | |
* | |
* @var string | |
*/ | |
private $linkCssClass = 'page-link'; | |
/** | |
* Show first and last links? | |
* | |
* @var bool | |
*/ | |
private $showFirstLastLink = true; | |
/** | |
* Show prev and next links? | |
* | |
* @var bool | |
*/ | |
private $showPrevNextLink = true; | |
/** | |
* Display all page links? | |
* | |
* @var bool | |
*/ | |
private $showAllLinks = false; | |
/** | |
* Get array value. | |
* | |
* It takes the array and a key name or a key path to access element in multidimensional array | |
* | |
* @param array $array The array to conduct the search on | |
* @param string $key The Key name or key path (a/b/c/d) | |
* @param mixed $default The default value | |
* @param null $callback | |
* | |
* @return mixed | |
*/ | |
function array_value( $array, $key, $default = NULL , $callback = NULL) { | |
if ( !is_array( $array ) ) { | |
return $default; | |
} | |
$key = trim( trim( $key ), '/' ); | |
$parts = explode( '/', $key ); | |
foreach ( $parts as $p ) { | |
$array = isset($array[ $p ]) ? $array[ $p ] : NULL; | |
if ( $array === NULL ) { | |
return $default; | |
} | |
} | |
if(is_callable($callback)) { | |
$array = call_user_func($callback,$array); | |
} | |
return $array; | |
} | |
/** | |
* Parse and format page container data | |
* | |
* @param array $data | |
*/ | |
private function setPageContainerData($data = array()) { | |
$data = is_array($data) ? $data : array(); | |
$data['tag'] = $this->array_value($data,'tag','ul','trim'); | |
$data['attrs'] = $this->array_value($data,'attrs',array()); | |
$data['attrs']['class'] = $this->array_value($data['attrs'],'class','pagination','trim'); | |
$this->pagerContainer = $data; | |
} | |
/** | |
* Set link container data | |
* | |
* @param array $data | |
*/ | |
private function setLinkContainerData($data = array()) { | |
$data = is_array($data) ? $data : array(); | |
$data['tag'] = $this->array_value($data,'tag','li','trim'); | |
$data['attrs'] = $this->array_value($data,'attrs',array()); | |
$data['attrs']['class'] = $this->array_value($data['attrs'],'class','','trim'); | |
$this->linkContainer = $data; | |
} | |
/** | |
* Generates a line of text | |
* | |
* @param int $tabs | |
* @param int $new_lines | |
* @param string $msg | |
* | |
* @return string | |
*/ | |
private function _m( $tabs = 0, $new_lines = 1, $msg = '' ) { | |
$tabs = (int) $tabs; | |
if ( $tabs < 0 ) { | |
$tabs = 0; | |
} | |
$new_lines = (int) $new_lines; | |
if ( $new_lines < 0 ) { | |
$new_lines = 0; | |
} | |
return str_repeat( " ", $tabs ).$msg.str_repeat( PHP_EOL, $new_lines); | |
} | |
/** | |
* tag markup | |
* | |
* @param array $attrs atg attributes | |
* | |
* @return string | |
*/ | |
private function __attr_markup( $attrs = array() ) { | |
$html = ''; | |
if ( is_array( $attrs ) && count( $attrs ) > 0 ) { | |
foreach ( $attrs as $k => $v ) { | |
$html .= " {$k}=\"".htmlentities( (string) $v, ENT_QUOTES )."\""; | |
} | |
} | |
return trim( $html ); | |
} | |
/** | |
* Generate the url for a pager | |
* | |
* @param $page_no | |
* | |
* @return mixed | |
*/ | |
private function _link_url( $page_no ) { | |
$page_no = (int) $page_no; | |
$url = str_replace( $this->pageNumberTemplateTag, $page_no, $this->pageUrl ); | |
return $url; | |
} | |
/** | |
* Constructor. We parse all params here | |
* | |
* @param array $params | |
*/ | |
function __construct( $params = array() ) { | |
/* Total records */ | |
$this->totalRecords = (int)$this->array_value($params,'totalRecords',0); | |
if ( $this->totalRecords < 0 ) { | |
$this->totalRecords = 0; | |
} | |
/* Records per page */ | |
$this->recordsPerPage = (int)$this->array_value($params,'recordsPerPage',self::DEFAULT_RECORDS_PER_PAGE); | |
if ( $this->recordsPerPage < 1 ) { | |
$this->recordsPerPage = 1; | |
} | |
/* max visible links */ | |
$this->maxVisibleLinks = (int)$this->array_value($params,'maxVisibleLinks',self::DEFAULT_MAX_VISIBLE_LINK); | |
if ( $this->maxVisibleLinks < 1 ) { | |
$this->maxVisibleLinks = 1; | |
} | |
/* Total pages */ | |
if ( $this->totalRecords > 0 ) { | |
$this->totalPages = (int) (ceil( $this->totalRecords / $this->recordsPerPage )); | |
} | |
else { | |
$this->totalPages = 0; | |
} | |
/* page URL */ | |
$this->pageUrl = $this->array_value($params,'pageUrl','','trim'); | |
/* page number template tag */ | |
$this->pageNumberTemplateTag = $this->array_value($params,'pageNumberTemplateTag',self::DEFAULT_PAGE_NUMBER_TEMPLATE_TAG,'trim'); | |
if ( $this->pageNumberTemplateTag == '' ) { | |
$this->pageNumberTemplateTag = self::DEFAULT_PAGE_NUMBER_TEMPLATE_TAG; | |
} | |
/* Current page number */ | |
$this->currentPageNumber = (int)$this->array_value($params,'currentPageNumber',1); | |
if ( $this->currentPageNumber < 1 ) { | |
$this->currentPageNumber = 1; | |
} | |
// page container | |
$this->setPageContainerData($this->array_value($params,'pagerContainer',array())); | |
// link container | |
$this->setLinkContainerData($this->array_value($params,'linkContainer',array())); | |
// Show first/last link | |
$this->showFirstLastLink = $this->array_value($params,'showFirstLastLink',true); | |
// Show prev/next link | |
$this->showPrevNextLink = $this->array_value($params,'showPrevNextLink',true); | |
// Show all links? | |
$this->showAllLinks = $this->array_value($params,'showAllLinks',false); | |
// page link css class | |
$this->linkCssClass = $this->array_value($params,'linkCssClass','page-link'); | |
} | |
/** | |
* Generate pager | |
* | |
* @return string | |
*/ | |
public function generatePager() { | |
if ( $this->pageUrl == '' ) { | |
return 'No page url specified!'; | |
} | |
if ( strpos( $this->pageUrl, $this->pageNumberTemplateTag ) === FALSE ) { | |
return 'Page number template tag '.$this->pageNumberTemplateTag.' not found in the url!'; | |
} | |
/** | |
* No paging if there is no page or only 1 page | |
*/ | |
if ( $this->totalPages <= 1 ) { | |
return ''; | |
} | |
# ======================================================== | |
# Process when all links should be shown | |
# ======================================================== | |
if($this->showAllLinks) { | |
$this->showFirstLastLink = false; | |
$this->showPrevNextLink = false; | |
} | |
# ======================================================== | |
# Init variables for use later on | |
# ======================================================== | |
$maxVisibleLinks = $this->maxVisibleLinks; | |
$currentPageNumber = $this->currentPageNumber; | |
$totalRecords = $this->totalRecords; | |
$recordsPerPage = $this->recordsPerPage; | |
$totalPages = $this->totalPages; | |
// Pager Container | |
$_ct = $this->array_value($this->pagerContainer,'tag','ul','trim'); | |
$_c_attrs_markup = $this->__attr_markup($this->array_value($this->pagerContainer,'attrs',array())); | |
// Link Container | |
$_lt = $this->array_value($this->linkContainer,'tag','li','trim'); | |
$_l_attrs = $this->array_value($this->linkContainer,'attrs',array()); | |
// link css class | |
$linkCssClass = $this->linkCssClass; | |
# ======================================================== | |
# Generate the html | |
# ======================================================== | |
$html = $this->_m( 0, 1, "<{$_ct} {$_c_attrs_markup}>" ); | |
// First link | |
if($this->showFirstLastLink) { | |
$liAttrs = $_l_attrs; | |
$liAttrs['class'] .= ($currentPageNumber == 1 ? ' disabled' : ''); | |
$html .= $this->_m( 1, 1, '<'.$_lt.' '.$this->__attr_markup( $liAttrs ).'>' ); | |
$linkAttr = array( | |
'class' => trim($linkCssClass.' page-link-first'), | |
'aria-label' => 'First Page', | |
'data-page' => 1, | |
'title' => 'First Page', | |
); | |
if($currentPageNumber != 1) { | |
$linkAttr['href'] = $this->_link_url( 1 ); | |
} | |
$html .= $this->_m( 2, 1, '<a '.$this->__attr_markup( $linkAttr ).'>' ); | |
$html .= $this->_m( 3, 1, '<span class="glyphicon glyphicon-fast-backward"></span>' ); | |
$html .= $this->_m( 2, 1, '</a>' ); | |
$html .= $this->_m( 1, 1, '</'.$_lt.'>' ); | |
} | |
// Prev link | |
if($this->showPrevNextLink) { | |
$liAttrs = $_l_attrs; | |
$liAttrs['class'] .= $currentPageNumber == 1 ? ' disabled' : ''; | |
$html .= $this->_m( 1, 1, '<'.$_lt.' '.$this->__attr_markup( $liAttrs ).'>' ); | |
$prevPageNumber = $currentPageNumber - 1; | |
if ( $prevPageNumber < 1 ) { | |
$prevPageNumber = 1; | |
} | |
$linkAttr = array( | |
'class' => trim($linkCssClass.' page-link-prev'), | |
'aria-label' => 'Previous Page', | |
'data-page' => $prevPageNumber, | |
'title' => 'Previous Page', | |
); | |
if($currentPageNumber != 1) { | |
$linkAttr['href'] = $this->_link_url( $prevPageNumber ); | |
} | |
$html .= $this->_m( 2, 1, '<a '.$this->__attr_markup( $linkAttr ).'>' ); | |
$html .= $this->_m( 3, 1, '<span class="glyphicon glyphicon-chevron-left"></span>' ); | |
$html .= $this->_m( 2, 1, '</a>' ); | |
$html .= $this->_m( 1, 1, '</'.$_lt.'>' ); | |
} | |
// generate visible links in middle | |
if($this->showAllLinks) { | |
$startIndex = 1; | |
$endIndex = $totalPages; | |
} else { | |
$startIndex = $currentPageNumber - $maxVisibleLinks; | |
$endIndex = $currentPageNumber + $maxVisibleLinks; | |
} | |
if ( $startIndex < 1 ) { | |
$startIndex = 1; | |
} | |
if ( $endIndex > $totalPages ) { | |
$endIndex = $totalPages; | |
} | |
// Left void region | |
if ( !$this->showAllLinks && $startIndex > 1 ) { | |
$liAttrs = $_l_attrs; | |
$liAttrs['class'] .= ' disabled'; | |
$html .= $this->_m( 1, 1, '<'.$_lt.' '.$this->__attr_markup( $liAttrs ).'>' ); | |
$html .= $this->_m( 2, 1, '<a '.$this->__attr_markup( array( | |
'class' => 'text-info', | |
) ).'>' ); | |
$html .= $this->_m( 3, 1, '<span>...</span>' ); | |
$html .= $this->_m( 2, 1, '</a>' ); | |
$html .= $this->_m( 1, 1, '</'.$_lt.'>' ); | |
} | |
// THE links ... | |
for ( $i = $startIndex; $i <= $endIndex; $i++ ) { | |
$liAttrs = $_l_attrs; | |
$liAttrs['class'] .= $i == $currentPageNumber ? ' active' : ''; | |
$html .= $this->_m( 1, 1, '<'.$_lt.' '.$this->__attr_markup( $liAttrs ).'>' ); | |
$linkAttrs = array( | |
'class' => trim($linkCssClass), | |
'aria-label' => "Page {$i} of {$totalPages}", | |
'data-page' => $i, | |
'title' => "Page {$i} of {$totalPages}", | |
); | |
if( $i != $currentPageNumber) { | |
$linkAttrs['href'] = $this->_link_url( $i ); | |
} | |
$html .= $this->_m( 2, 1, '<a '.$this->__attr_markup( $linkAttrs ).'>' ); | |
$html .= $this->_m( 3, 1, '<span>'.$i.'</span>' ); | |
$html .= $this->_m( 2, 1, '</a>' ); | |
$html .= $this->_m( 1, 1, '</'.$_lt.'>' ); | |
} | |
// Right void region | |
if ( !$this->showAllLinks && $endIndex < $totalPages ) { | |
$liAttrs = $_l_attrs; | |
$liAttrs['class'] .= ' disabled'; | |
$html .= $this->_m( 1, 1, '<'.$_lt.' '.$this->__attr_markup( $liAttrs ).'>' ); | |
$html .= $this->_m( 2, 1, '<a '.$this->__attr_markup( array( | |
'class' => 'text-info', | |
) ).'>' ); | |
$html .= $this->_m( 3, 1, '<span>...</span>' ); | |
$html .= $this->_m( 2, 1, '</a>' ); | |
$html .= $this->_m( 1, 1, '</'.$_lt.'>' ); | |
} | |
// Next link | |
if($this->showPrevNextLink) { | |
$liAttrs = $_l_attrs; | |
$liAttrs['class'] .= $currentPageNumber == $totalPages ? ' disabled' : ''; | |
$html .= $this->_m( 1, 1, '<'.$_lt.' '.$this->__attr_markup( $liAttrs ).'>' ); | |
$nextPageNumber = $currentPageNumber + 1; | |
if ( $nextPageNumber >= $totalPages ) { | |
$nextPageNumber = $totalPages; | |
} | |
$linkAttr = array( | |
'class' => trim($linkCssClass.' page-link-next'), | |
'aria-label' => 'Next Page', | |
'data-page' => $nextPageNumber, | |
'title' => 'Next Page', | |
); | |
if($currentPageNumber != $totalPages) { | |
$linkAttr['href'] = $this->_link_url( $nextPageNumber ); | |
} | |
$html .= $this->_m( 2, 1, '<a '.$this->__attr_markup( $linkAttr ).'>' ); | |
$html .= $this->_m( 3, 1, '<span class="glyphicon glyphicon-chevron-right"></span>' ); | |
$html .= $this->_m( 2, 1, '</a>' ); | |
$html .= $this->_m( 1, 1, '</'.$_lt.'>' ); | |
} | |
// Last link | |
if($this->showFirstLastLink) { | |
$liAttrs = $_l_attrs; | |
$liAttrs['class'] .= $currentPageNumber == $totalPages ? ' disabled' : ''; | |
$html .= $this->_m( 1, 1, '<'.$_lt.' '.$this->__attr_markup( $liAttrs ).'>' ); | |
$linkAttr = array( | |
'class' => trim($linkCssClass.' page-link-last'), | |
'aria-label' => 'Last Page', | |
'data-page' => $totalPages, | |
'title' => 'Last Page', | |
); | |
if($currentPageNumber != $totalPages) { | |
$linkAttr['href'] = $this->_link_url( $totalPages ); | |
} | |
$html .= $this->_m( 2, 1, '<a '.$this->__attr_markup( $linkAttr ).'>' ); | |
$html .= $this->_m( 3, 1, '<span class="glyphicon glyphicon-fast-forward"></span>' ); | |
$html .= $this->_m( 2, 1, '</a>' ); | |
$html .= $this->_m( 1, 1, '</'.$_lt.'>' ); | |
} | |
// End of generation (almost!) | |
$html .= $this->_m( 0, 1, "</{$_ct}>" ); | |
return $html; | |
} | |
/** | |
* Generates records info in the form of "Showing {start} - {end} of {total}" e.g. "Showing 1 - 20 of 78" | |
* | |
* @param null $callback Optional callback function, which are called with $start,$end and $total params, | |
* allowing user to override the text generated. | |
* | |
* @return string | |
*/ | |
public function generateRecordsInfo($callback = null) { | |
$totalRecords = (int)$this->totalRecords; | |
if($totalRecords <= 0) { | |
return ''; | |
} | |
$recordsPerPage = (int)$this->recordsPerPage; | |
if($recordsPerPage <= 0) { | |
return ''; | |
} | |
$currentPageNo = (int)$this->currentPageNumber; | |
if($currentPageNo < 1) { | |
$currentPageNo = 1; | |
} | |
$startIndex = ($currentPageNo - 1) * $recordsPerPage + 1; | |
$endIndex = $currentPageNo * $recordsPerPage; | |
if($endIndex > $totalRecords) { | |
$endIndex = $totalRecords; | |
} | |
if(is_callable($callback)) { | |
return call_user_func($callback,$startIndex,$endIndex,$totalRecords); | |
} | |
$text = "Showing {$startIndex} - {$endIndex} of {$totalRecords}"; | |
return $text; | |
} | |
} | |
# simple usage | |
$simplePager = new SimplePager(array( | |
'totalRecords' => 228, | |
'recordsPerPage' => 15, | |
'maxVisibleLinks' => 10, | |
'pageUrl' => 'http://mysite.net/some-page.php?_pageId={%pageNum%}', | |
'pageNumberTemplateTag' => '{%pageNum%}', | |
'currentPageNumber' => $_GET['_pageId'], | |
'pagerContainer' => array( | |
'tag' => 'div', | |
'attrs' => array( | |
'id' => 'top-pager', | |
'class' => 'pager' | |
) | |
), | |
'linkContainer' => array( | |
'tag' => 'span', | |
'attrs' => array( | |
'class' => 'page-link' | |
) | |
), | |
'linkCssClass' => '' | |
)); | |
echo $simplePager->generatePager(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment