tangra logo
   
[ class tree: tangra_lib ] [ index: tangra_lib ] [ all elements ]
 

Source for file paginate_db_data.class.php

Documentation is available at paginate_db_data.class.php

  1. <?php
  2. // *** Tangra (Application Framework and Tools for PHP)
  3. //  $Id$
  4. //
  5.  
  6. /**
  7.  * Contains Paginate_DB_Data class
  8.  *
  9.  * @package tangra_lib
  10.  * @subpackage db
  11.  */
  12.  
  13. /**
  14.  *
  15.  */
  16. require_once(TANGRA_MAIN_DIR.'db/db_connection.class.php');
  17.  
  18.  
  19. /**
  20.  * Used to paginate db data
  21.  *
  22.  * This class is useful for working with DB data when you need pagination
  23.  *
  24.  * @package tangra_lib
  25.  * @subpackage db
  26.  * @see Grid
  27.  */
  28. class Paginate_DB_Data extends Tangra_Class {
  29.     /**
  30.      * If set to false some methods will throw exception if you try to fetch non existing page.
  31.      *
  32.      * @var boolean 
  33.      * @access private
  34.      */
  35.     private $forgiving;
  36.  
  37.     /**
  38.      * Holds current page index
  39.      *
  40.      * @var unknown_type 
  41.       * @access private
  42.      */
  43.     private $current_page = 0;
  44.  
  45.     /**
  46.      * Holds total number of rows
  47.      *
  48.      * @var unknown_type 
  49.      * @access private
  50.      */
  51.     private $total_rows;
  52.  
  53.     /**
  54.      * Holds size of the page
  55.      *
  56.      * @var unknown_type 
  57.      * @access private
  58.      */
  59.     private $page_size;
  60.  
  61.     /**
  62.      * Holds count of currently available pages
  63.      *
  64.      * @var unknown_type 
  65.      * @access private
  66.      */
  67.     private $total_pages;
  68.  
  69.     /**
  70.      * SQL select statement for selecting data
  71.      *
  72.      * @var unknown_type 
  73.      */
  74.     private $sql_select;
  75.  
  76.     /**
  77.      * SQL select statement for counting rows that match "where" clause
  78.      *
  79.      * @var unknown_type 
  80.      */
  81.     private $sql_count;
  82.  
  83.  
  84.     /**
  85.      * Constructor
  86.      *
  87.      * @param integer $page_size Page size. How many rows will each page have
  88.      * @param string $sql_select SQL statement that will be used to set actual data
  89.      * @param string $sql_count SQL statement that will be used to count rows matching the "where" clause. Note that returned value have to be aliased  with "as total_rows", otherwise  you will get an exception
  90.      * @param boolean $forgiving If set to false some methods will throw exception if you try to fetch non existing page. If true - fetch* methods will guess some safe value. Default is false
  91.      */
  92.     function __construct($page_size$sql_select$sql_count$forgiving true{
  93.         $this->set_page_size($page_size);
  94.  
  95.         $this->set_sql_select($sql_select);
  96.  
  97.         //sql_count must be as "select count(id) as total_rows from some_table where..."
  98.         $this->set_sql_count($sql_count);
  99.  
  100.         $this->set_forgiving($forgiving);
  101.     }
  102.  
  103.     /**
  104.      * Returns current page
  105.      *
  106.      * @return integer 
  107.      */
  108.     public function get_current_page({
  109.         return $this->current_page;
  110.     }
  111.  
  112.  
  113.     /**
  114.      * Sets page size
  115.      *
  116.      * @param integer $page_size 
  117.      */
  118.     public function set_page_size($page_size{
  119.         tangra_if_not_int_throw_e($page_size);
  120.         $this->page_size = $page_size;
  121.     }
  122.  
  123.  
  124.     /**
  125.      * Returns page size
  126.      *
  127.      * @return unknown 
  128.      */
  129.     public function get_page_size({
  130.         return $this->page_size;
  131.     }
  132.  
  133.  
  134.     /**
  135.      * Sets SQL statement used to get actual data
  136.      *
  137.      * @param unknown_type $sql_select 
  138.      */
  139.     public function set_sql_select($sql_select{
  140.         $this->sql_select = $sql_select;
  141.     }
  142.  
  143.  
  144.     /**
  145.      * Gets SQL statement used to get actual data
  146.      *
  147.      * @return string 
  148.      */
  149.     public function get_sql_select({
  150.         return $this->sql_select;
  151.     }
  152.  
  153.  
  154.     /**
  155.      * Sets SQL statement that will be used to count rows matching the "where" clause. Note that returned value have to be aliased  with "as total_rows", otherwise  you will get an exception
  156.      *
  157.      * @param string $sql_count 
  158.      */
  159.     public function set_sql_count($sql_count{
  160.         $this->sql_count = $sql_count;
  161.     }
  162.  
  163.  
  164.     /**
  165.      * Gets SQL statement that will be used to count rows matching the "where" clause
  166.      *
  167.      * @return string 
  168.      */
  169.     public function get_sql_count({
  170.         return $this->sql_count;
  171.     }
  172.  
  173.  
  174.     /**
  175.      * Sets forgiving mode. If set to false some methods will throw exception if you try to fetch non existing page. If true - fetch* methods will guess some safe value. Default is false
  176.      *
  177.      * @param boolean $forgiving 
  178.      */
  179.     public function set_forgiving($forgiving{
  180.         $this->forgiving = $forgiving true false;
  181.     }
  182.  
  183.  
  184.     /**
  185.      * Gets forgiving mode
  186.      *
  187.      * @return unknown 
  188.      * @see Paginate_DB_Data::set_forgiving
  189.      */
  190.     public function get_forgiving({
  191.         return $this->forgiving;
  192.     }
  193.  
  194.  
  195.     /**
  196.      * Check the forgivenes mode and throws exception if mode is false
  197.      *
  198.      * @param unknown_type $exception 
  199.      * @access private
  200.      */
  201.     protected function ask_for_forgivenes($exception{
  202.         if (!$this->get_forgiving()) {
  203.             throw $exception;
  204.         }
  205.     }
  206.  
  207.  
  208.     /**
  209.      * Sets total rows.
  210.      *
  211.      * @param unknown_type $total_rows 
  212.      */
  213.     protected function set_total_rows($total_rows{
  214.         $this->total_rows = $total_rows;
  215.     }
  216.  
  217.  
  218.     /**
  219.      * Returns total rows (current sql_count)
  220.      *
  221.      * @return integer 
  222.      */
  223.     public function get_total_rows({
  224.         return $this->total_rows;
  225.     }
  226.  
  227.  
  228.     /**
  229.      * Sets total pages for current sql count
  230.      *
  231.      * @param integer $total_pages 
  232.      */
  233.     public function set_total_pages($total_pages{
  234.         $this->total_pages = $total_pages;
  235.     }
  236.  
  237.  
  238.     /**
  239.      * Returns total pages
  240.      *
  241.      * @return integer 
  242.      */
  243.     public function get_total_pages({
  244.         return $this->total_pages;
  245.     }
  246.  
  247.  
  248.     /**
  249.      * Executes $sql_count and recalculates total rows and total pages
  250.      *
  251.      * @param DB_Connection $dbc 
  252.      */
  253.     public function refresh(DB_Connection $dbc{
  254.         $rez $dbc->execute($this->get_sql_count());
  255.         $rez_obj $rez->fetch_object();
  256.         $this->set_total_rows($rez_obj->TOTAL_ROWS);
  257.  
  258.         if ($this->get_total_rows()) {
  259.             $this->set_total_pages($this->calculate_total_pages());
  260.         else {
  261.             $this->set_total_pages(0);
  262.         }
  263.  
  264.     }
  265.  
  266.  
  267.     /**
  268.      * Calculates start of current page
  269.      *
  270.      * @return integer 
  271.      * @internal
  272.      */
  273.     protected function calculate_start({
  274.         return $this->get_current_page($this->get_page_size();
  275.     }
  276.  
  277.  
  278.     /**
  279.      * Calculates total pages
  280.      *
  281.      * @return unknown 
  282.      * @internal
  283.      */
  284.     protected function calculate_total_pages({
  285.         return ceil($this->get_total_rows($this->get_page_size());
  286.     }
  287.  
  288.  
  289.     /**
  290.      * Gathers current page rows
  291.      *
  292.      * @param DB_Connection $dbc 
  293.      * @return array Returned rows
  294.      * @internal
  295.      */
  296.     protected function _fetch_current_page(DB_Connection $dbc{
  297.         $start $this->calculate_start();
  298.  
  299.         $rez $dbc->select_limit($this->get_sql_select()$this->get_page_size()$start);
  300.  
  301.         $ret array();
  302.         while(!$rez->is_eof()) {
  303.             $row $rez->fetch_row();
  304.  
  305.             array_push($ret$row);
  306.         }
  307.  
  308.         return $ret;
  309.     }
  310.  
  311.  
  312.     /**
  313.      * Gathers current page rows
  314.      *
  315.      * @param DB_Connection $dbc 
  316.      * @return array Returned rows
  317.      */
  318.     public function fetch_current_page(DB_Connection $dbc{
  319.         $this->refresh($dbc);
  320.  
  321.         return $this->_fetch_current_page($dbc);
  322.     }
  323.  
  324.  
  325.     /**
  326.      * Sets current page
  327.      *
  328.      * @param integer $current_page 
  329.      * @internal
  330.      */
  331.     protected function set_current_page($current_page{
  332.         tangra_if_not_int_throw_e($current_page);
  333.         if ($this->is_valid_page($current_page)) {
  334.             $this->current_page = $current_page;
  335.         else {
  336.             if ($this->get_forgiving()) {
  337.                 //correcting invalid page
  338.                 if ($current_page 0{
  339.                     $this->current_page = 0;
  340.                 else {
  341.                     $this->current_page = $this->get_total_pages(1;
  342.                 }
  343.             else {
  344.                 $this->ask_for_forgivenes(new Tangra_Exception('No such page: '.$current_page));
  345.             }
  346.         }
  347.     }
  348.  
  349.  
  350.     /**
  351.      * checks if $page is valid page index, i.e. there is such page
  352.      *
  353.      * @param integer $page 
  354.      * @return boolean 
  355.      * @internal
  356.      */
  357.     private function is_valid_page($page{
  358.         $ret false;
  359.         if ($page >= && $page <= $this->get_total_pages()) {
  360.             $ret true;
  361.         }
  362.  
  363.         return $ret;
  364.     }
  365.  
  366.  
  367.     /**
  368.      * Fetches first page
  369.      *
  370.      * @param DB_Connection $dbc 
  371.      * @return array 
  372.      */
  373.     public function fetch_first_page(DB_Connection $dbc{
  374.         $this->refresh($dbc);
  375.         $this->set_current_page(0);
  376.  
  377.         return $this->_fetch_current_page($dbc);
  378.     }
  379.  
  380.  
  381.     /**
  382.      * Fetches last page
  383.      *
  384.      * @param DB_Connection $dbc 
  385.      * @return array 
  386.      */
  387.     public function fetch_last_page(DB_Connection $dbc{
  388.         $this->refresh($dbc);
  389.         $this->set_current_page($this->get_total_pages(1);
  390.  
  391.         return $this->_fetch_current_page($dbc);
  392.     }
  393.  
  394.  
  395.     /**
  396.      * Fetches next page
  397.      *
  398.      * @param DB_Connection $dbc 
  399.      * @return array 
  400.      */
  401.     public function fetch_next_page(DB_Connection $dbc{
  402.         $this->refresh($dbc);
  403.         $next_page $this->get_current_page(1;
  404.  
  405.         if (!($next_page <= $this->get_total_pages())) {
  406.             $next_page $this->get_total_pages();
  407.         }
  408.  
  409.         $this->set_current_page($next_page);
  410.  
  411.         return $this->_fetch_current_page($dbc);
  412.     }
  413.  
  414.  
  415.     /**
  416.      * Fetches previous page
  417.      *
  418.      * @param DB_Connection $dbc 
  419.      * @return array 
  420.      */
  421.     public function fetch_prev_page(DB_Connection $dbc{
  422.         $this->refresh($dbc);
  423.         $prev_page $this->get_current_page(1;
  424.  
  425.         if (!($prev_page >= 0)) {
  426.             $this->ask_for_forgivenes(new Tangra_Exception('No such page: '.$current_page));
  427.             $prev_page 0;
  428.         }
  429.  
  430.         $this->set_current_page($prev_page);
  431.         return $this->_fetch_current_page($dbc);
  432.     }
  433.  
  434.  
  435.     /**
  436.      * Fetches page specified by $page
  437.      *
  438.      * @param integer $page Page number
  439.      * @param DB_Connection $dbc 
  440.      * @return array 
  441.      */
  442.     public function fetch_page($pageDB_Connection $dbc{
  443.         tangra_if_not_int_throw_e($page);
  444.         $this->refresh($dbc);
  445.         $this->set_current_page($page);
  446.         return $this->_fetch_current_page($dbc);
  447.     }
  448. }