PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/install/1/includes/classes/SqlPager.php

https://github.com/ibnoe/Microweber
PHP | 395 lines | 233 code | 52 blank | 110 comment | 39 complexity | 59553a41cd6771722da1f383bfc91ade MD5 | raw file
  1. <?php
  2. /**
  3. * This class make paging very simple - just provide it with the query to page, and it will do the rest.
  4. * It uses the LIMIT keyword to do this. Currently, it support only MySQL.
  5. * Example:
  6. * $pager = new SqlPager("SELECT name FROM ${config['db_prefix']}Users WHERE status=1");
  7. * print $pager->getLink("first") . ' | ' . $pager->getLink("previous");
  8. * $pager->printPager();
  9. * print $pager->getLink("next") . ' | ' . $pager->getLink("last");
  10. * $this_page = $pager->getPage();
  11. */
  12. class SqlPager {
  13. // Public Variables
  14. var $query; /// The SQL Query to be paged.
  15. var $items_per_page; /// The Number of items that should be shown in 1 page
  16. var $page; /// The current page number
  17. var $total_items; /// Total number of records
  18. var $total_pages; /// Total number of pages
  19. var $page_link = ""; /// The file that must be used while making links to pages.
  20. /**
  21. * This is the template used to create links when the getLink() is called.
  22. * %%PAGE_LINK%% - current page url & sp_page=PageNumber . Example: demo.php?param=value&sp_page=3
  23. */
  24. var $link_template = '<a href="%%PAGE_LINK%%" class="page-%%CLASS%%">%%TEXT%%</a>';
  25. /**
  26. * This is the template used to create links when the getStatus() is called. Possible substitutions...
  27. * %%PAGE%%
  28. * %%FROM%%
  29. * %%TO%%
  30. * %%TOTAL_PAGES%%
  31. * %%TOTAL_ITEMS%%
  32. */
  33. var $status_template = 'Viewing %%FROM%% - %%TO%% of %%TOTAL_ITEMS%%';
  34. ///The current mode of the system. Possible values are 'd' = Development Mode, 't' = Testing Mode, 'p' = Production Mode
  35. var $mode = 'd';
  36. var $opt = array(
  37. 'links_count' => 10, // If 0, shows all links
  38. );
  39. ///The text used in the pager is customizable. HTML is allowed.
  40. var $text = array(
  41. 'previous' => '&lt;' , 'next' => '&gt;', //Next and Previous Texts
  42. 'first' => '&lt;&lt;', 'last' => '&gt;&gt;', //First and Last Links
  43. 'current_page_indicator' => array(
  44. 'left' => '[',
  45. 'right' => ']'
  46. ),
  47. 'link_seperator' => " " //The text between the paging links(Page numbers).
  48. );
  49. ///Private Variables
  50. var $_sql_resource;
  51. var $_pager_query;
  52. /**
  53. * Constructor
  54. * Argument : $query - The query that should be used for paging
  55. * $items_per_page - The default number of items per page - defaults to 10 [OPTIONAL]
  56. */
  57. function SqlPager($query, $items_per_page = 10) {
  58. $query = preg_replace('/ LIMIT .+/i','',$query);//Remove the 'limitation' if there is one
  59. $this->query = $query;
  60. //Before anything, get all the necessary data.
  61. //Get the value of $items_per_page from the query or from the parameter
  62. $this->items_per_page = ($this->_getParam('sp_items_per_page')) ?
  63. $this->_getParam('sp_items_per_page') : $items_per_page;
  64. //Get the current page number
  65. $this->page = ($this->_getParam('sp_page')) ? $this->_getParam('sp_page') : 1;
  66. $this->page_link = basename($_SERVER['PHP_SELF']);
  67. $offset = ($this->page - 1) * $this->items_per_page;
  68. $this->_pager_query = $query . " LIMIT $offset," . $this->items_per_page;
  69. global $sql;
  70. $total_items_sql = $sql->getSql($this->query);
  71. $this->total_items = $sql->fetchNumRows($total_items_sql);
  72. $this->total_pages = ceil($this->total_items / $this->items_per_page);
  73. }
  74. /**
  75. * Returns the SQL resource of the pager.
  76. * Return : The SQL resource of the pager.
  77. */
  78. function getSql() {
  79. //:TODO: Use DB abstraction
  80. global $sql;
  81. $this->_sql_resource = $sql->getSql($this->_pager_query);
  82. return $this->_sql_resource;
  83. }
  84. /**
  85. * Returns all the items for one page in an array.
  86. * Returns : All the items for one page in a list.
  87. */
  88. function getPage() {
  89. global $sql;
  90. $resource = $this->getSql();
  91. $result = array();
  92. while($row = $sql->fetchAssoc($resource)) {
  93. $result[] = $row;
  94. }
  95. return $result;
  96. }
  97. //////////////////////////////////// Functions that print ///////////////////////////////////////
  98. /**
  99. * Prints the pager. Shows links to pages as numbers - except for the current page. The number of links to be shown
  100. * is decided by the $opt['links_count'] member variable. If that is 0, all links are shown. If its 5, then
  101. * 5 links are shown.
  102. */
  103. function printPager($return_data = false) {
  104. if($this->total_pages == 1) return; //Just 1 page - don't need pager.
  105. $from = 1;
  106. $to = $this->total_pages;
  107. // Decides many page numbers should be shown
  108. if($this->opt['links_count']) {
  109. $difference = intval($this->opt['links_count'] / 2);
  110. $from = $this->page - $difference + 1;
  111. $to = $this->page + $difference;
  112. //Make sure the numbers are in range.
  113. if($from < 1) {
  114. //The numbers that cannot be put in the right side can be put in the left side
  115. $to = $to + (-$from);//$from is negetive
  116. $from = 1;
  117. }
  118. if($to > $this->total_pages) {
  119. $from = $from - ($to - $this->total_pages);
  120. $to = $this->total_pages;
  121. if($from < 1) $from = 1;
  122. }
  123. }
  124. $to_print = '';
  125. for($i = $from; $i <= $to; $i++) {
  126. if($i == $this->page) { //Current Page
  127. $to_print .= $this->text['current_page_indicator']['left'] . $i . $this->text['current_page_indicator']['right'];
  128. } else {
  129. $to_print .= '<a class="sp-page-number" href="' . $this->getLinkToPage($i) . '">'.$i."</a>";
  130. }
  131. $to_print .= $this->text['link_seperator'];
  132. }
  133. if($return_data) return $to_print;
  134. else print $to_print;
  135. }
  136. /**
  137. * Returns the link to the page of the given page number
  138. * Argument: $page - The page number of the page of which's link you want.
  139. * Return: The url of the page - index.php?sp_page=2
  140. */
  141. function getLinkToPage($page) {
  142. if($page > $this->total_pages) return '';
  143. return $this->_getLinkParameters($this->page_link,array('sp_page'=>$page));
  144. }
  145. /**
  146. * Return the Next/Previous and First/Last Link based on the argument. The link will be formated
  147. * using the $link_template member variable of this class.
  148. * Arguments : $dir(String) - the direction of the link you want. Possible values are...
  149. * - 'next' get the next link
  150. * - 'previous' get the previous link.
  151. * - 'first' link to the first
  152. * - 'last' links to last page.
  153. * Returns: The HTML of the link - based on $link_template member variable
  154. */
  155. function getLink($dir) {
  156. $dir = strtolower($dir);
  157. //We just make the template here. Depending on the value of '$dir' the values to be inserted in
  158. // the place of the replacement texts(like %%PAGE%%) will change.
  159. $replace_these = array("%%PAGE%%","%%CLASS%%","%%TEXT%%", "%%PAGE_LINK%%"); //Stuff to replace
  160. if($dir === "previous" or $dir === "back" or $dir === 'prev') { //Get the back link
  161. $back = $this->page-1;
  162. $back = ($back > 0) ? $back : 1; //Never let the value of $back be lesser than 1(first page)
  163. $with_these = array($back,"previous",$this->text['previous']);
  164. } elseif($dir === "next" or $dir === "forward") { //Get the forward link
  165. $next = $this->page+1;
  166. $next = ($next > $this->total_pages) ? $this->total_pages : $next; //Never let the value of $next go beyond the total number of pages
  167. $with_these = array($next,"next",$this->text['next']);
  168. } elseif($dir === "first" or $dir === "start" or $dir === 'beginning') { //Get the first link
  169. $with_these = array(1,"first",$this->text['first']);
  170. } elseif($dir === "last" or $dir === "end") { //Get the last link.
  171. $with_these = array($this->total_pages,"last",$this->text['last']);
  172. }
  173. $page_link = $this->_getLinkParameters($this->page_link, array('sp_page'=> $with_these[0]));
  174. array_push($with_these, $page_link); //Add the page link at the beginning of the array.
  175. $link = str_replace($replace_these, $with_these, $this->link_template); //Replace the texts
  176. return $link;
  177. }
  178. /**
  179. * Create and return a link with the parameters given as the function argument.
  180. */
  181. function makeLink($params) {
  182. return $this->_getLinkParameters($this->page_link, $params);
  183. }
  184. //////////////////////////////////////// HTML/JavaScript Blocks ///////////////////////////////////
  185. /**
  186. * Returns the status of the current page. Use the $status_template member variable as a template.
  187. */
  188. function getStatus() {
  189. $from = ($this->page * $this->items_per_page) - $this->items_per_page + 1;
  190. $to = $from + $this->items_per_page - 1;
  191. $to = ($to > $this->total_items) ? $this->total_items : $to;
  192. $replace_these = array('%%FROM%%', '%%TO%%', '%%TOTAL_ITEMS%%', '%%PAGE%%', '%%TOTAL_PAGES%%');
  193. $with_these = array($from, $to, $this->total_items, $this->page, $this->total_pages);
  194. $status = str_replace($replace_these, $with_these, $this->status_template);
  195. return $status;
  196. }
  197. /**
  198. * Shows a Dropdown menu with values 5,10,20, 25, 50, 100. On selecting one option, that much items will be
  199. * shown in one page.
  200. */
  201. function printItemsPerPageDropDown() {
  202. $page_link = $this->_getLinkParameters($this->page_link, array('sp_items_per_page'=>'__ITEMS_PER_PAGE__','sp_page'=>1));//Go to 1st page when items_per_page is changed
  203. ?>
  204. <script language="javascript" type="text/javascript">
  205. function itemsPerPageChooser(number) {
  206. var url = "<?=$page_link?>";
  207. url = url.replace(/__ITEMS_PER_PAGE__/g,number);
  208. url = url.replace(/\&amp;/g,"&");
  209. document.location.href = url;
  210. return false;
  211. }
  212. </script>
  213. <form name="item_per_page_dropdown" onSubmit="return itemsPerPageChooser(document.getElementById('sp_items_per_page').value)" action="">
  214. <?php $this->_printHiddenFields(array('sp_items_per_page', 'sp_page', 'action')); ?>
  215. Show <select name="sp_items_per_page" id="sp_items_per_page" onChange="itemsPerPageChooser(this.value)">
  216. <?php
  217. $values = array(5, 10, 20, 25, 50, 100);
  218. foreach($values as $i) {
  219. $sel="";
  220. if($i == $this->items_per_page) $sel = "selected='selected'"; //Make sure the current page is selected.
  221. print " <option value='$i'$sel>$i</option>";
  222. }
  223. ?></select> items per page.<input type="submit" name="action" value="Go" />
  224. </form>
  225. <?php
  226. }
  227. /**
  228. * Input box based navigation. Shows a Input box where the users can type in a page number to go
  229. * to that page number. Very useful for sites with a large number of pages.
  230. */
  231. function printGoToInput() {
  232. $size = 4;
  233. if($this->total_pages < 10) $size = 1;
  234. else if($this->total_pages < 100) $size = 2;
  235. else if($this->total_pages < 1000) $size = 3;
  236. $this->_printGoToPageJsFunction();
  237. ?>
  238. <form onSubmit="return goToPage(this.sp_page.value)" action="">
  239. <?php $this->_printHiddenFields(array('sp_page', 'action')); ?>
  240. <?= t('Page')?> <input type="text" name="sp_page" size="<?=$size?>" value="<?=$this->page?>" />
  241. <input type="submit" name="action" value="<?= t('Go')?>" /> <?=t('of %d',$this->total_pages)?>
  242. </form>
  243. <?php
  244. }
  245. /**
  246. * This function displays a dropdown box with all pages. Selecting a different page jumps to that page.
  247. */
  248. function printGoToDropDown() {
  249. $this->_printGoToPageJsFunction();
  250. ?>
  251. <form onSubmit="return goToPage(this.sp_page.value)" action="">
  252. <?php $this->_printHiddenFields(array('sp_page', 'action')); ?>
  253. <?= t('Page')?> <select name="sp_page" onChange="goToPage(this.value);">
  254. <?php
  255. for($i=1; $i<=$this->total_pages; $i++) {
  256. print "<option value='$i'";
  257. if($i==$this->page) print " selected='selected'";
  258. print ">$i</option>";
  259. }
  260. ?>
  261. </select><input type="submit" name="action" value="<?= t('Go')?>" />
  262. </form>
  263. <?php
  264. }
  265. /**
  266. * This creates hidden field for all query fields except for the ones specified in the argument.
  267. */
  268. function _printHiddenFields($except = array()) {
  269. $all_request = $_GET+$_POST; // $_REQUEST has session, cookie info- we don't want that.
  270. foreach($all_request as $key=>$value) {
  271. if(!in_array($key, $except)) {
  272. print "<input type='hidden' name='$key' value='$value' />\n";
  273. }
  274. }
  275. }
  276. /**
  277. * Creates a goToPage javascript function. This is used by 2 different methods -
  278. * the printGoToInput() and printGoToDropDown(). I am moving it to its own method
  279. * to make sure it appears only once.
  280. */
  281. function _printGoToPageJsFunction() {
  282. static $shown = 0;
  283. if($shown) return; //Makes sure this script is inserted only once
  284. $shown = 1;
  285. $page_link = $this->_getLinkParameters($this->page_link, array('sp_page'=>'__PAGE__'));
  286. ?>
  287. <script language="javascript" type="text/javascript">
  288. function goToPage(page) {
  289. var url = "<?=$page_link?>";
  290. url = url.replace(/__PAGE__/g,page);
  291. url = url.replace(/\&amp;/g,"&");
  292. if(page > <?=$this->total_pages?> || page < 1) alert(<?=t('Invalid page number. Please use a number between 1 and %d',$this->total_pages)?>");
  293. else document.location.href = url;
  294. return false;
  295. }
  296. </script>
  297. <?php
  298. }
  299. //////////////////////////////////////// Private Functions ///////////////////////////////////////
  300. /**
  301. * Returns the User input from $_REQUEST after escaping it using mysql_real_escape_string()
  302. * Argument : $string - Parameter name
  303. * Return : Parameter value, escaped.
  304. */
  305. function _getParam($string) {
  306. if(!isset($_REQUEST[$string])) return '';
  307. if(is_array($_REQUEST[$string])) return $_REQUEST[$string];
  308. return addslashes($_REQUEST[$string]);
  309. }
  310. /**
  311. * Adds the given parameters to the given URL are retuns the result. The returned URL will be XHTML complient
  312. * Argument : $url - The URL of the page.
  313. * $params(Array) - An associative array holding the parameters that should be added to the URL.
  314. * Example : _getLinkParameters('index.php?user=1',array('sp_page'=>7,'sp_items_per_page'=>5))
  315. */
  316. function _getLinkParameters($url , $params = array()) {
  317. $use_existing_arguments = true;
  318. if($use_existing_arguments) $params = $params + $_GET;
  319. if(!$params) return $url;
  320. $link = $url;
  321. if(strpos($link,'?') === false) $link .= '?'; //If there is no '?' add one at the end
  322. elseif(!preg_match('/(\?|\&(amp;)?)$/',$link)) $link .= '&amp;'; //If there is no '&' at the END, add one.
  323. $params_arr = array();
  324. foreach($params as $key=>$value) {
  325. if(gettype($value) == 'array') { //Handle array data properly
  326. foreach($value as $val) {
  327. $params_arr[] = $key . '[]=' . urlencode($val);
  328. }
  329. } else {
  330. $params_arr[] = $key . '=' . urlencode($value);
  331. }
  332. }
  333. $link .= implode('&amp;',$params_arr);
  334. return $link;
  335. }
  336. /**
  337. * Shows an error message based on mode.
  338. */
  339. function _error($message) {
  340. if($this->mode == 'd') die($message);
  341. elseif($this->mode == 't') print($message);
  342. }
  343. }