Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
25 / 25
CRAP
100.00% covered (success)
100.00%
113 / 113
Pager
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
25 / 25
52
100.00% covered (success)
100.00%
113 / 113
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
5 / 5
 getCurrentPageNo
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 setCurrentPageNo
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 setLimit
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getTotalNums
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 setTotalNums
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getLimit
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getOffset
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
4 / 4
 getTotalPageNums
100.00% covered (success)
100.00%
1 / 1
4
100.00% covered (success)
100.00%
8 / 8
 getPages
100.00% covered (success)
100.00%
1 / 1
16
100.00% covered (success)
100.00%
38 / 38
 getPagesAsArray
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getCurrentPage
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getCurrentPageAsArray
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getNextPage
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 getNextPageAsArray
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getPrevPage
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 getPrevPageAsArray
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getFirstPage
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 getFirstPageAsArray
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getLastPage
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 getLastPageAsArray
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 isFirst
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 isLast
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
3 / 3
 getStartItemNo
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
2 / 2
 getLastItemNo
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
<?php
namespace Puyo\Pager;
use \Puyo\Pager\Page as Page;
/**
 * ページャ
 *
 * 使用例:
 * 【コントローラ】
 *     // インスタンス生成(カレントページを表すGETパラメタ,表示件数,コントローラ)
 *     $pager = new Pager($_GET['page'], $limit, $_SERVER['REQUEST_URI']);
 *
 * 【モデル】
 *     // "SQL_CALC_FOUND_ROWS"を付けてSQL文を実行
 *     // SELECTと同時に,LIMITを指定しない場合の全件数がカウントされる
 *     $sql = "SELECT SQL_CALC_FOUND_ROWS a, b, c ";
 *     $sql.=   "FROM t_hoge";
 *     $sql.=  "ORDER BY a ";
 *     $sql.=  "LIMIT = " . $pager -> getLimit() . " ";
 *     $sql.= "OFFSET = " . $pager -> getOffset() . " ";
 *     $rs = SQLを実行($sql);
 *
 *     // "SQL_CALC_FOUND_ROWS"でカウントした件数を取得
 *     $sql = "SELECT found_rows() rows";
 *     $numOfRows = mysql_query($sql, $db);
 *
 *     // ページャに全件数を設定
 *     $pager -> setTotalItems($numOfRows[0]['rows']);
 *
 * 【コントローラ】
 *     // Smartyテンプレートにassign
 *     $smarty -> assign('records', $rs);    // 抽出したレコード
 *     $smarty -> assign('pager', $pager);    // ページャ
 *
 * 【ビュー】
 *     {assign var="firstPage" value=$pager->getFirstPage()}
 *     {assign var="prevPage" value=$pager->getPreviousPage()}
 *     {assign var="nextPage" value=$pager->getNextPage()}
 *     {assign var="lastPage" value=$pager->getLastPage()}
 *
 *     {if $pager->isFirst()}
 *         最初
 *     {else}
 *         <a href="{$firstPage.url}">最初</a>
 *     {/if}
 *
 *     {if $prevPage}
 *         <a href="{$prevPage.url}">前</a>
 *     {else}
 *         前
 *     {/if}
 *
 *     {foreach from=$pager->getPages() item=page}
 *         {if $page.pageNo == $pager->getCurrentPageNo()}
 *             {$page.pageNo}
 *         {else}
 *             <a href="{$page.url}">{$page.pageNo}</a>
 *         {/if}
 *     {/foreach}
 *
 *
 *     {if $nextPage}
 *         <a href="{$nextPage.url}">次</a>
 *     {else}
 *         次
 *     {/if}
 *
 *     {if $pager->isLast()}
 *         最後
 *     {else}
 *         <a href="{$lastPage.url}">最後</a>
 *     {/if}
 *
 * @author y.kushida
 * @version 0.1 R54
 */
class Pager
{
    /**
     * カレントページ
     * @var integer
     */
    private $currentPageNo;
    
    /**
     * ページ内件数
     * @var integer
     */
    private $perPage;
    
    /**
     * 全レコード数
     * @var integer
     */
    private $totalItems = 0;
    
    /**
     * 表示するページ数
     * @var int
     */
    private $visiblePages = 5;
    
    /**
     * コントローラのファイル名/path
     * @var string
     */
    private $controllerURI;
    
    /**
     * ページ番号を表すパラメータの名前
     * @var string
     */
    private $paramName = "page";
    
    /**
     * コンストラクタ
     *
     * @param int $currentPageNo        カレントページ番号.デフォルト1
     * @param int $perPage                ページ内表示件数.デフォルト10件
     * @param string $controllerURI    送信先
     * @param string $paramName            (optional) ページ番号を表すパラメタの名前.デフォルトpage
     */
    public function __construct($currentPageNo=1, $perPage=10, $controllerURI=null, $paramName="page") {
        $this->setCurrentPageNo($currentPageNo);
        $this->perPage = $perPage;
        $this->controllerURI = $controllerURI;
        $this->paramName = $paramName;
    }
    
    /**
     * カレントのページ番号を返す
     * @return int ページ番号
     */
    public function getCurrentPageNo() {
        return (int)$this->currentPageNo;
    }
    /**
     * カレントページ番号を設定する
     * @param int $pageNo
     */
    public function setCurrentPageNo($pageNo) {
        $pageNo = intVal($pageNo);
        if($pageNo < 1) {
            $pageNo = 1;
        }
        $this->currentPageNo = $pageNo;
    }
    
    /**
     * ページ内件数を設定する
     * @param int $perPage
     */
    public function setLimit($perPage) {
        $this->perPage = intVal($perPage);
    }
    
    /**
     * 全レコード数を返す
     */
    public function getTotalNums() {
        return $this->totalItems;
    }
    
    /**
     * 全レコード数を設定する
     * @param int $totalNums
     */
    public function setTotalNums($totalNums) {
        $this->totalItems = $totalNums;
    }
    
    /**
     * ページ内件数を返す.
     * @return int ページ内件数
     */
    public function getLimit() {
        return (int)$this->perPage;
    }
    
    /**
     * オフセットを返す.
     * @return int オフセット
     */
    public function getOffset() {
        $currentPageNo = $this->currentPageNo;
        $perPage = $this->getLimit();
        
        $offset = $perPage * ($currentPageNo - 1);
        
        return $offset;
    }
    
    /**
     * 全ページ数を返す
     * @return int 全ページ数
     */
    public function getTotalPageNums() {
        $totalPages = null;
        
        $totalItems = $this->totalItems;
        $perPage = $this->perPage;
        
        if($totalItems === 0 || $perPage === 0) {
            return 0;
        }
        $totalPages = floor($totalItems / $perPage);
        // 全件数/ページ内件数で余りが出れば+1ページ
        $totalPages += ($totalItems % $perPage != 0) ? 1 : 0;
        
        return (int)$totalPages;
    }
    
    /**
     * ページリストを返す
     * @param int $visiblePages ページングナビのページ番号の数
     * @return Page[]
     */
    public function getPages($visiblePages=null) {
        if(!isset($visiblePages)) {
            $visiblePages = $this->visiblePages;
        }
        $totalPages = $this->getTotalPageNums();
        $currentPageNo = $this->currentPageNo;
        // カレントページのチェック
        if($currentPageNo > $totalPages) {
            $currentPageNo = $this->currentPageNo = $totalPages;
        }
        
        $startDiff = null;
        $endDiff = null;
        
        // 表示する先頭のページ番号を求める(中心に来るように)
        $half = floor($visiblePages / 2);
        // 頭のチェック
        $startPageNo = $currentPageNo;
        for($i = 0; $i < $half; $i++) {
            if($startPageNo <= 1) {
                break;
            }
            $startPageNo--;
        }
        if($startPageNo > $currentPageNo - $half) {    // 途中で先頭ページ出現
            $startDiff = $startPageNo - ($currentPageNo - $visiblePages);    //差分
        }
        // おしりのチェック
        $endPageNo = $currentPageNo;
        for($i = 0; $i < $half; $i++) {
            if($endPageNo >= $totalPages) {
                break;
            }
            $endPageNo++;
        }
        if($endPageNo < $currentPageNo + $half) {    // 途中で最終ページ出現
            $endDiff = ($currentPageNo + $half) - $endPageNo;    // 差分
        }
        
        // 差分の調整
        for($i = 0; $i < $startDiff; $i++) {
            if($endPageNo >= $totalPages) {
                break;
            }
            $endPageNo++;
        }
        for($i = 0; $i < $endDiff; $i++) {
            if($startPageNo <= 1) {
                break;
            }
            $startPageNo--;
        }
        
        // ページなし
        if($totalPages < 1) {
            return array();
        }
        $result = [];
        for($i = 0; $i < $visiblePages && $startPageNo <= $endPageNo; $i++) {
            $result[] = new Page($startPageNo, $this->controllerURI, $this->paramName);
            $startPageNo++;
        }
        return $result;
    }
    public function getPagesAsArray($visiblePages=null) {
        $arrPages = array();
        foreach($this->getPages($visiblePages) as $page) {
            $arrPages[] = $page->toArray();
        }
        return $arrPages;
    }
    
    /**
     * カレントページを返す
     * @return Page カレントページ
     */
    public function getCurrentPage() {
        $page = new Page($this->currentPageNo, $this->controllerURI, $this->paramName);
        return $page;
    }
    /**
     * カレントページを配列で返す
     * @return array カレントページ
     */
    public function getCurrentPageAsArray() {
        $page = $this->getCurrentPage();
        return $page->toArray();
    }
    
    /**
     * 次ページを返す.
     * 次ページがない場合はNullを返す.
     * @return \Puyo\Pager\Page 次ページ
     */
    public function getNextPage() {
        $pageNo = $this->currentPageNo + 1;
        if($pageNo > $this->getTotalPageNums()) {
            return null;
        }
        $page = new Page($pageNo, $this->controllerURI, $this->paramName);
        return $page;
    }
    /**
     * 次ページを配列で返す.
     * 次ページがない場合はNullを返す.
     * @return array|null 次ページ
     */
    public function getNextPageAsArray() {
        $page = $this->getNextPage();
        if($page === null) {
            return null;
        }
        return $page->toArray();
    }
    
    /**
     * 前ページを返す.
     * 前ページがない場合はNullを返す.
     * @return Page 前ページ
     */
    public function getPrevPage() {
        $pageNo = $this->currentPageNo - 1;
        if($pageNo < 1) {
            return null;
        }
        $page = new Page($pageNo, $this->controllerURI, $this->paramName);
        return $page;
    }
    public function getPrevPageAsArray() {
        $page = $this->getPrevPage();
        if($page === null) {
            return null;
        }
        return $page->toArray();
    }
    
    /**
     * 先頭ページを返す.
     * @return Page 先頭ページ
     */
    public function getFirstPage() {
        $pageNo = 1;
        $page = new Page($pageNo, $this->controllerURI, $this->paramName);
        return $page;
    }
    public function getFirstPageAsArray() {
        return $this->getFirstPage()->toArray();
    }
    
    /**
     * 最終ページを返す
     * @return Page 最終ページ
     */
    public function getLastPage() {
        $pageNo = $this->getTotalPageNums();
        $page = new Page($pageNo, $this->controllerURI, $this->paramName);
        return $page;
    }
    public function getLastPageAsArray() {
        return $this->getLastPage()->toArray();
    }
    
    /**
     * カレントページが先頭ページであるか否かを返す
     * @return bool 先頭ページであるか否か
     */
    public function isFirst() {
        if($this->currentPageNo == 1) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * カレントページが最終ページであるか否かを返す
     * @return bool 最終ページであるか否か
     */
    public function isLast() {
        if($this->currentPageNo == $this->getTotalPageNums()) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
     * 表示中のアイテムが何件目からかを返す(Smarty Template用)
     * @return int 何件目か
     */
    public function getStartItemNo() {
        $start = (((($this->currentPageNo) - 1) * ($this->perPage)) + 1);
        return $start;
    }
    
    /**
     * 表示中のアイテムが何件目までかを返す(Smarty Template用)
     * @return int 何件目か
     */
    public function getLastItemNo() {
        if($this->isLast()) {
            $end = $this->totalItems;
        } else {
            $end = (($this->currentPageNo) * ($this->perPage));
        }
        return $end;
    }
}