You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. <?php
  2. /**
  3. * Pagination abstract class
  4. *
  5. * <code>
  6. * $pager = new RPage();
  7. * $pager->total(100);
  8. * $pager->setSize(21);
  9. * $pager->setKeyword("page");
  10. * $pager->setPath("pager.php");
  11. * $pager->setQuery("a=b&pager=%{PAGE_NO}&d=1");
  12. * echo $pager;
  13. * echo "offset:" . $pager->offset();
  14. * </code>
  15. *
  16. * @author iwind <iwind.iwind@gmail.com>
  17. * @link http://ifphp.cn
  18. * @version $Id$
  19. * @package rock
  20. * @subpackage plugin.pager
  21. */
  22. /**
  23. * Pagination abstract class
  24. *
  25. * 实现了RPage接口的一些方法
  26. *
  27. * @version $Id$
  28. * @package if
  29. * @subpackage plugin.pager
  30. */
  31. abstract class RPage {
  32. private $keyword;
  33. private $total;
  34. private $path;
  35. private $size;
  36. private $properties;
  37. private $query;
  38. private $length;
  39. private $pageSetSize = 11;
  40. private $rows = array();
  41. /**
  42. * 是否加载了本地化对象
  43. *
  44. * @var boolean
  45. * @since 1.0
  46. */
  47. private $localeLoaded = false;
  48. /**
  49. * 语言配置
  50. *
  51. * @var array
  52. * @since 1.0
  53. */
  54. private $messages = array();
  55. /**
  56. * 分页中代码当前页码的常量
  57. *
  58. */
  59. const PAGER_VARIABLE_STRING = "%{PAGE_NO}";
  60. /**
  61. * 构造器
  62. *
  63. * @since 2.0
  64. */
  65. function __construct() {
  66. $this->path = $_SERVER["PHP_SELF"];
  67. }
  68. /**
  69. * 取得当前页码,第一页为1
  70. *
  71. * @return integer
  72. */
  73. function current() {
  74. $keyword = $this->keyword();
  75. $pageNo = intval(x($keyword));
  76. if ($pageNo <= 0) {
  77. $pageNo = 1;
  78. }
  79. return min($pageNo, $this->length());
  80. }
  81. /**
  82. * 取得下一页页码
  83. *
  84. * @return integer
  85. */
  86. function next() {
  87. $length = $this->length();
  88. $current = $this->current();
  89. return $current < $length ? ($current + 1) : $length;
  90. }
  91. /**
  92. * 取得上一页页码
  93. *
  94. * @return integer
  95. */
  96. function prev() {
  97. $length = $this->length();
  98. $current = $this->current();
  99. return $current > 1 ? ($current - 1) : 1;
  100. }
  101. /**
  102. * 取得记录开始的偏移量
  103. *
  104. * @return integer
  105. */
  106. function offset() {
  107. $offset = $this->size() * ($this->current() - 1);
  108. if ($offset < 0) {
  109. $offset = 0;
  110. }
  111. if($offset >= $this->total()){
  112. $offset = max($this->size () * ($this->length () - 1), 0);
  113. }
  114. return $offset;
  115. }
  116. /**
  117. * 设置内容总数
  118. *
  119. * @param integer $total 内容总数
  120. * @return RPage
  121. */
  122. function setTotal($total) {
  123. $this->total = intval($total);
  124. if ($this->total < 0) {
  125. throw new Exception("content total '{$total}' can't be small than 0");
  126. }
  127. return $this;
  128. }
  129. /**
  130. * 数据总数
  131. *
  132. * @return integer
  133. * @since 1.0
  134. */
  135. function total() {
  136. return $this->total;
  137. }
  138. /**
  139. * 设置分页链接中的关键字
  140. *
  141. * @param string $keyword 关键字
  142. * @return RPage
  143. */
  144. function setKeyword($keyword) {
  145. $this->keyword = $keyword;
  146. return $this;
  147. }
  148. /**
  149. * 取得分页用的关键字
  150. *
  151. * 从1.0开始,如果没有关键字,则默认为page
  152. *
  153. * @return string
  154. */
  155. function keyword() {
  156. if (!$this->keyword) {
  157. $this->keyword = "page";
  158. }
  159. return $this->keyword;
  160. }
  161. /**
  162. * 设置每页记录数
  163. *
  164. * @param integer $size 大于0的数字
  165. * @return RPage
  166. */
  167. function setSize($size) {
  168. $this->size = intval($size);
  169. if ($this->size < 1) {
  170. throw new Exception("page size '{$size}' can't be small than 1");
  171. }
  172. return $this;
  173. }
  174. /**
  175. * 取得每页记录数
  176. *
  177. * @return integer
  178. */
  179. function size() {
  180. if ($this->size < 1) {
  181. $this->size = 10;
  182. }
  183. return $this->size;
  184. }
  185. /**
  186. * 设置链接的路径
  187. *
  188. * @param string $path 路径
  189. * @return RPage
  190. */
  191. function setPath($path) {
  192. $this->path = $path;
  193. return $this;
  194. }
  195. /**
  196. * 取得程序路径
  197. *
  198. * @return string
  199. * @since 1.0
  200. */
  201. function path() {
  202. return $this->path;
  203. }
  204. /**
  205. * 设置属性
  206. *
  207. * @param array $properties 属性列表
  208. * @return RPage
  209. */
  210. function setProperties(array $properties) {
  211. $this->properties = $properties;
  212. return $this;
  213. }
  214. /**
  215. * 取得设置的属性
  216. *
  217. * @return array
  218. * @since 1.0
  219. */
  220. function properties() {
  221. return $this->properties;
  222. }
  223. /**
  224. * 设置查询
  225. *
  226. * @param mixed $query string|array
  227. * @return RPage
  228. */
  229. function setQuery($query) {
  230. if (is_array($query)) {
  231. $_query = array();
  232. foreach ($query as $key => $value) {
  233. if ($key == $this->keyword()) {
  234. continue;
  235. }
  236. if (is_array($value)) {
  237. foreach ($value as $key1=>$value1) {
  238. $_query[] = "{$key}[]=" . urlencode($value1);
  239. }
  240. }
  241. else {
  242. $_query[] = "{$key}=" . urlencode($value);
  243. }
  244. }
  245. $query = implode("&", $_query);
  246. }
  247. $this->query = $query;
  248. return $this;
  249. }
  250. /**
  251. * 添加查询条件
  252. *
  253. * <code>
  254. * $page->addQuery(array(
  255. * "e" => 5,
  256. * "f" => 6
  257. * ));
  258. * $page->addQuery("g=7");
  259. * </code>
  260. *
  261. * @param mixed $query string|array
  262. * @return RPage
  263. * @since 1.0.3
  264. */
  265. function addQuery($query) {
  266. if (is_array($query)) {
  267. $_query = array();
  268. foreach ($query as $key => $value) {
  269. if ($key == $this->keyword()) {
  270. continue;
  271. }
  272. if (is_array($value)) {
  273. foreach ($value as $key1=>$value1) {
  274. $_query[] = "{$key}[]=" . urlencode($value1);
  275. }
  276. }
  277. else {
  278. $_query[] = "{$key}=" . urlencode($value);
  279. }
  280. }
  281. $query = implode("&", $_query);
  282. }
  283. $this->query .= ($this->query ? "&" : "") . $query;
  284. return $this;
  285. }
  286. /**
  287. * 开启自动构造查询条件功能
  288. *
  289. * @param boolean $bool 是否开启该功能
  290. * @param string|array $except 要去除的参数名
  291. * @param string|array $only 限制的参数名
  292. * @return RPage
  293. * @since 1.0.3
  294. */
  295. function setAutoQuery($bool = true, $except = "", $only = "") {
  296. if (!is_array($except)) {
  297. $except = preg_split("/\\s+,\\s+/", $except);
  298. }
  299. if (!is_array($only) && strlen($only) > 0) {
  300. $only = preg_split("/\\s+,\\s+/", $only);
  301. }
  302. if ($bool) {
  303. $x = xn();
  304. foreach ($x as $name => $value) {
  305. if ($except && in_array($name, $except)) {
  306. unset($x[$name]);
  307. }
  308. if ($only && !in_array($name, $only)) {
  309. unset($x[$name]);
  310. }
  311. }
  312. $this->setQuery($x);
  313. }
  314. return $this;
  315. }
  316. /**
  317. * 取得查询
  318. *
  319. * @return array
  320. * @since 1.0
  321. */
  322. function query() {
  323. return $this->query;
  324. }
  325. /**
  326. * 取得一个分页好号对应的URL
  327. *
  328. * @param integer $pageNo 分页号
  329. * @return string
  330. * @since 1.0
  331. */
  332. function url($pageNo) {
  333. $query = $this->query();
  334. if (strstr($query, self::PAGER_VARIABLE_STRING)) {
  335. $query = str_replace(self::PAGER_VARIABLE_STRING, $pageNo, $query);
  336. }
  337. else {
  338. if ($query == "") {
  339. $query = $this->keyword() . "=" . $pageNo;
  340. }
  341. else {
  342. $query .= "&" . $this->keyword() . "=" . $pageNo;
  343. }
  344. }
  345. return $this->path() . "?" . $query;
  346. }
  347. /**
  348. * 取得总分页数
  349. *
  350. * @return integer
  351. * @since 1.0
  352. */
  353. function length() {
  354. if ($this->size() == 0) {
  355. return 0;
  356. }
  357. return ceil($this->total()/$this->size());
  358. }
  359. /**
  360. * 添加记录
  361. *
  362. * @param mixed $row 记录
  363. * @return RPage
  364. */
  365. function addRow($row) {
  366. $this->rows[] = $row;
  367. return $this;
  368. }
  369. /**
  370. * 添加记录集
  371. *
  372. * @param array $rows 记录集
  373. * @return RPage
  374. */
  375. function addRows(array $rows) {
  376. foreach ($rows as $row) {
  377. $this->rows[] = $row;
  378. }
  379. return $this;
  380. }
  381. /**
  382. * 取得记录集
  383. *
  384. * @return array
  385. */
  386. function rows() {
  387. return $this->rows;
  388. }
  389. /**
  390. * 设置记录集
  391. *
  392. * @param array|iterable $rows 记录集
  393. * @return RPage
  394. */
  395. function setRows($rows) {
  396. $this->rows = $rows;
  397. return $this;
  398. }
  399. /**
  400. * 取得键值对应的消息文本
  401. *
  402. * @param string $key 键值
  403. * @return string
  404. * @since 1.0
  405. */
  406. protected function message($key) {
  407. if (!$this->localeLoaded) {
  408. $locale = __LANG__;
  409. if (!$locale) {
  410. $locale = "default";
  411. }
  412. $message = x("~" . $key);
  413. if ($message) {
  414. return $message;
  415. }
  416. //简写
  417. $dirname = dirname(__FILE__) . "/lang";
  418. $langFile = $dirname . "/" . $locale . ".php";
  419. if (is_file($langFile)) {
  420. require($langFile);
  421. $this->messages = $message;
  422. }
  423. $this->localeLoaded = true;
  424. }
  425. if (is_array($this->messages) && array_key_exists($key, $this->messages)) {
  426. return $this->messages[$key];
  427. }
  428. return null;
  429. }
  430. /**
  431. * 转换成字符串
  432. *
  433. * @return string
  434. */
  435. public abstract function __toString();
  436. /**
  437. * 设置分页集尺寸
  438. *
  439. * @param integer $num 大于1
  440. * @return RPage
  441. * @since 1.0
  442. */
  443. function setPageSetNum($num){
  444. $this->pageSetSize = $num;
  445. return $this;
  446. }
  447. /**
  448. * 取得分页集尺寸
  449. *
  450. * @return integer
  451. * @since 1.0
  452. */
  453. function pageSetNum(){
  454. return $this->pageSetSize;
  455. }
  456. static function pageWithStyle($style, array $params = null) {
  457. exit(__METHOD__ . " need to be implemented.");
  458. }
  459. }
  460. ?>