00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 class PaginatorHelper extends AppHelper {
00034
00035
00036
00037
00038
00039 var $helpers = array('Html', 'Ajax');
00040
00041
00042
00043
00044
00045 var $__defaultModel = null;
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 var $options = array();
00069
00070
00071
00072
00073
00074
00075 function params($model = null) {
00076 if (empty($model)) {
00077 $model = $this->defaultModel();
00078 }
00079 if (!isset($this->params['paging']) || empty($this->params['paging'][$model])) {
00080 return null;
00081 }
00082 return $this->params['paging'][$model];
00083 }
00084
00085
00086
00087
00088
00089
00090 function options($options = array()) {
00091 if (is_string($options)) {
00092 $options = array('update' => $options);
00093 }
00094
00095 if (!empty($options['paging'])) {
00096 if (!isset($this->params['paging'])) {
00097 $this->params['paging'] = array();
00098 }
00099 $this->params['paging'] = array_merge($this->params['paging'], $options['paging']);
00100 unset($options['paging']);
00101 }
00102 $model = $this->defaultModel();
00103
00104 if (!empty($options[$model])) {
00105 if (!isset($this->params['paging'][$model])) {
00106 $this->params['paging'][$model] = array();
00107 }
00108 $this->params['paging'][$model] = array_merge($this->params['paging'][$model], $options[$model]);
00109 unset($options[$model]);
00110 }
00111 $this->options = array_filter(array_merge($this->options, $options));
00112 }
00113
00114
00115
00116
00117
00118
00119 function current($model = null) {
00120 $params = $this->params($model);
00121
00122 if (isset($params['page'])) {
00123 return $params['page'];
00124 }
00125 return 1;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135 function sortKey($model = null, $options = array()) {
00136 if (empty($options)) {
00137 $params = $this->params($model);
00138 $options = array_merge($params['defaults'], $params['options']);
00139 }
00140
00141 if (isset($options['sort']) && !empty($options['sort'])) {
00142 if (preg_match('/(?:\w+\.)?(\w+)/', $options['sort'], $result) && isset($result[1])) {
00143 if ($result[0] == $this->defaultModel()) {
00144 return $result[1];
00145 }
00146 }
00147 return $options['sort'];
00148 } elseif (isset($options['order']) && is_array($options['order'])) {
00149 return key($options['order']);
00150 } elseif (isset($options['order']) && is_string($options['order'])) {
00151 if (preg_match('/(?:\w+\.)?(\w+)/', $options['order'], $result) && isset($result[1])) {
00152 return $result[1];
00153 }
00154 return $options['order'];
00155 }
00156 return null;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166 function sortDir($model = null, $options = array()) {
00167 $dir = null;
00168
00169 if (empty($options)) {
00170 $params = $this->params($model);
00171 $options = array_merge($params['defaults'], $params['options']);
00172 }
00173
00174 if (isset($options['direction'])) {
00175 $dir = strtolower($options['direction']);
00176 } elseif (isset($options['order']) && is_array($options['order'])) {
00177 $dir = strtolower(current($options['order']));
00178 }
00179
00180 if ($dir == 'desc') {
00181 return 'desc';
00182 }
00183 return 'asc';
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 function prev($title = '<< Previous', $options = array(), $disabledTitle = null, $disabledOptions = array()) {
00195 return $this->__pagingLink('Prev', $title, $options, $disabledTitle, $disabledOptions);
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 function next($title = 'Next >>', $options = array(), $disabledTitle = null, $disabledOptions = array()) {
00207 return $this->__pagingLink('Next', $title, $options, $disabledTitle, $disabledOptions);
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 function sort($title, $key = null, $options = array()) {
00219 $options = array_merge(array('url' => array(), 'model' => null), $options);
00220 $url = $options['url'];
00221 unset($options['url']);
00222
00223 if (empty($key)) {
00224 $key = $title;
00225 $title = __(Inflector::humanize(preg_replace('/_id$/', '', $title)), true);
00226 }
00227 $dir = 'asc';
00228 $sortKey = $this->sortKey($options['model']);
00229 $isSorted = ($sortKey === $key || $sortKey === $this->defaultModel() . '.' . $key);
00230
00231 if ($isSorted && $this->sortDir($options['model']) === 'asc') {
00232 $dir = 'desc';
00233 }
00234
00235 if (is_array($title) && array_key_exists($dir, $title)) {
00236 $title = $title[$dir];
00237 }
00238
00239 $url = array_merge(array('sort' => $key, 'direction' => $dir), $url, array('order' => null));
00240 return $this->link($title, $url, $options);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250 function link($title, $url = array(), $options = array()) {
00251 $options = array_merge(array('model' => null, 'escape' => true), $options);
00252 $model = $options['model'];
00253 unset($options['model']);
00254
00255 if (!empty($this->options)) {
00256 $options = array_merge($this->options, $options);
00257 }
00258 if (isset($options['url'])) {
00259 $url = array_merge((array)$options['url'], (array)$url);
00260 unset($options['url']);
00261 }
00262 $url = $this->url($url, true, $model);
00263
00264 $obj = isset($options['update']) ? 'Ajax' : 'Html';
00265 $url = array_merge(array('page' => $this->current($model)), $url);
00266 $url = array_merge(Set::filter($url, true), array_intersect_key($url, array('plugin'=>true)));
00267 return $this->{$obj}->link($title, $url, $options);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 function url($options = array(), $asArray = false, $model = null) {
00278 $paging = $this->params($model);
00279 $url = array_merge(array_filter(Set::diff(array_merge($paging['defaults'], $paging['options']), $paging['defaults'])), $options);
00280
00281 if (isset($url['order'])) {
00282 $sort = $direction = null;
00283 if (is_array($url['order'])) {
00284 list($sort, $direction) = array($this->sortKey($model, $url), current($url['order']));
00285 }
00286 unset($url['order']);
00287 $url = array_merge($url, compact('sort', 'direction'));
00288 }
00289
00290 if ($asArray) {
00291 return $url;
00292 }
00293 return parent::url($url);
00294 }
00295
00296
00297
00298
00299 function __pagingLink($which, $title = null, $options = array(), $disabledTitle = null, $disabledOptions = array()) {
00300 $check = 'has' . $which;
00301 $_defaults = array('url' => array(), 'step' => 1, 'escape' => true, 'model' => null, 'tag' => 'div');
00302 $options = array_merge($_defaults, (array)$options);
00303 $paging = $this->params($options['model']);
00304
00305 if (!$this->{$check}($options['model']) && (!empty($disabledTitle) || !empty($disabledOptions))) {
00306 if (!empty($disabledTitle) && $disabledTitle !== true) {
00307 $title = $disabledTitle;
00308 }
00309 $options = array_merge($_defaults, (array)$disabledOptions);
00310 } elseif (!$this->{$check}($options['model'])) {
00311 return null;
00312 }
00313
00314 foreach (array_keys($_defaults) as $key) {
00315 ${$key} = $options[$key];
00316 unset($options[$key]);
00317 }
00318 $url = array_merge(array('page' => $paging['page'] + ($which == 'Prev' ? $step * -1 : $step)), $url);
00319
00320 if ($this->{$check}($model)) {
00321 return $this->link($title, $url, array_merge($options, array('escape' => $escape)));
00322 } else {
00323 return $this->Html->tag($tag, $title, $options, $escape);
00324 }
00325 }
00326
00327
00328
00329
00330
00331
00332 function hasPrev($model = null) {
00333 return $this->__hasPage($model, 'prev');
00334 }
00335
00336
00337
00338
00339
00340
00341 function hasNext($model = null) {
00342 return $this->__hasPage($model, 'next');
00343 }
00344
00345
00346
00347
00348
00349
00350
00351 function hasPage($model = null, $page = 1) {
00352 if (is_numeric($model)) {
00353 $page = $model;
00354 $model = null;
00355 }
00356 $paging = $this->params($model);
00357 return $page <= $paging['pageCount'];
00358 }
00359
00360
00361
00362
00363 function __hasPage($model, $page) {
00364 $params = $this->params($model);
00365 if (!empty($params)) {
00366 if ($params["{$page}Page"] == true) {
00367 return true;
00368 }
00369 }
00370 return false;
00371 }
00372
00373
00374
00375
00376
00377 function defaultModel() {
00378 if ($this->__defaultModel != null) {
00379 return $this->__defaultModel;
00380 }
00381 if (empty($this->params['paging'])) {
00382 return null;
00383 }
00384 list($this->__defaultModel) = array_keys($this->params['paging']);
00385 return $this->__defaultModel;
00386 }
00387
00388
00389
00390
00391
00392
00393 function counter($options = array()) {
00394 if (is_string($options)) {
00395 $options = array('format' => $options);
00396 }
00397
00398 $options = array_merge(
00399 array(
00400 'model' => $this->defaultModel(),
00401 'format' => 'pages',
00402 'separator' => ' of '
00403 ),
00404 $options);
00405
00406 $paging = $this->params($options['model']);
00407 if ($paging['pageCount'] == 0) {
00408 $paging['pageCount'] = 1;
00409 }
00410 $start = 0;
00411 if ($paging['count'] >= 1) {
00412 $start = (($paging['page'] - 1) * $paging['options']['limit']) + 1;
00413 }
00414 $end = $start + $paging['options']['limit'] - 1;
00415 if ($paging['count'] < $end) {
00416 $end = $paging['count'];
00417 }
00418
00419 switch ($options['format']) {
00420 case 'range':
00421 if (!is_array($options['separator'])) {
00422 $options['separator'] = array(' - ', $options['separator']);
00423 }
00424 $out = $start . $options['separator'][0] . $end . $options['separator'][1] . $paging['count'];
00425 break;
00426 case 'pages':
00427 $out = $paging['page'] . $options['separator'] . $paging['pageCount'];
00428 break;
00429 default:
00430 $replace = array(
00431 '%page%' => $paging['page'],
00432 '%pages%' => $paging['pageCount'],
00433 '%current%' => $paging['current'],
00434 '%count%' => $paging['count'],
00435 '%start%' => $start,
00436 '%end%' => $end
00437 );
00438 $out = str_replace(array_keys($replace), array_values($replace), $options['format']);
00439 break;
00440 }
00441 return $this->output($out);
00442 }
00443
00444
00445
00446
00447
00448
00449
00450 function numbers($options = array()) {
00451 if ($options === true) {
00452 $options = array(
00453 'before' => ' | ', 'after' => ' | ',
00454 'first' => 'first', 'last' => 'last',
00455 );
00456 }
00457
00458 $options = array_merge(
00459 array(
00460 'tag' => 'span',
00461 'before'=> null, 'after'=> null,
00462 'model' => $this->defaultModel(),
00463 'modulus' => '8', 'separator' => ' | ',
00464 'first' => null, 'last' => null,
00465 ),
00466 (array)$options);
00467
00468 $params = array_merge(array('page'=> 1), (array)$this->params($options['model']));
00469 unset($options['model']);
00470
00471 if ($params['pageCount'] <= 1) {
00472 return false;
00473 }
00474
00475 extract($options);
00476 unset($options['tag'], $options['before'], $options['after'], $options['model'],
00477 $options['modulus'], $options['separator'], $options['first'], $options['last']);
00478
00479 $out = '';
00480
00481 if ($modulus && $params['pageCount'] > $modulus) {
00482 $half = intval($modulus / 2);
00483 $end = $params['page'] + $half;
00484
00485 if ($end > $params['pageCount']) {
00486 $end = $params['pageCount'];
00487 }
00488 $start = $params['page'] - ($modulus - ($end - $params['page']));
00489 if ($start <= 1) {
00490 $start = 1;
00491 $end = $params['page'] + ($modulus - $params['page']) + 1;
00492 }
00493
00494 if ($first && $start > 1) {
00495 $offset = ($start <= (int)$first) ? $start - 1 : $first;
00496 if ($offset < $start - 1) {
00497 $out .= $this->first($offset, array('tag' => $tag, 'separator' => $separator));
00498 } else {
00499 $out .= $this->first($offset, array('tag' => $tag, 'after' => $separator, 'separator' => $separator));
00500 }
00501 }
00502
00503 $out .= $before;
00504
00505 for ($i = $start; $i < $params['page']; $i++) {
00506 $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options)) . $separator;
00507 }
00508
00509 $out .= $this->Html->tag($tag, $params['page'], array('class' => 'current'));
00510 if ($i != $params['pageCount']) {
00511 $out .= $separator;
00512 }
00513
00514 $start = $params['page'] + 1;
00515 for ($i = $start; $i < $end; $i++) {
00516 $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options)). $separator;
00517 }
00518
00519 if ($end != $params['page']) {
00520 $out .= $this->Html->tag($tag, $this->link($i, array('page' => $end), $options));
00521 }
00522
00523 $out .= $after;
00524
00525 if ($last && $end < $params['pageCount']) {
00526 $offset = ($params['pageCount'] < $end + (int)$last) ? $params['pageCount'] - $end : $last;
00527 if ($offset <= $last && $params['pageCount'] - $end > $offset) {
00528 $out .= $this->last($offset, array('tag' => $tag, 'separator' => $separator));
00529 } else {
00530 $out .= $this->last($offset, array('tag' => $tag, 'before' => $separator, 'separator' => $separator));
00531 }
00532 }
00533
00534 } else {
00535 $out .= $before;
00536
00537 for ($i = 1; $i <= $params['pageCount']; $i++) {
00538 if ($i == $params['page']) {
00539 $out .= $this->Html->tag($tag, $i, array('class' => 'current'));
00540 } else {
00541 $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options));
00542 }
00543 if ($i != $params['pageCount']) {
00544 $out .= $separator;
00545 }
00546 }
00547
00548 $out .= $after;
00549 }
00550
00551 return $this->output($out);
00552 }
00553
00554
00555
00556
00557
00558
00559
00560 function first($first = '<< first', $options = array()) {
00561 $options = array_merge(
00562 array(
00563 'tag' => 'span',
00564 'after'=> null,
00565 'model' => $this->defaultModel(),
00566 'separator' => ' | ',
00567 ),
00568 (array)$options);
00569
00570 $params = array_merge(array('page'=> 1), (array)$this->params($options['model']));
00571 unset($options['model']);
00572
00573 if ($params['pageCount'] <= 1) {
00574 return false;
00575 }
00576 extract($options);
00577 unset($options['tag'], $options['after'], $options['model'], $options['separator']);
00578
00579 $out = '';
00580
00581 if (is_int($first) && $params['page'] > $first) {
00582 if ($after === null) {
00583 $after = '...';
00584 }
00585 for ($i = 1; $i <= $first; $i++) {
00586 $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options));
00587 if ($i != $first) {
00588 $out .= $separator;
00589 }
00590 }
00591 $out .= $after;
00592 } elseif ($params['page'] > 1) {
00593 $out = $this->Html->tag($tag, $this->link($first, array('page' => 1), $options)) . $after;
00594 }
00595 return $out;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604 function last($last = 'last >>', $options = array()) {
00605 $options = array_merge(
00606 array(
00607 'tag' => 'span',
00608 'before'=> null,
00609 'model' => $this->defaultModel(),
00610 'separator' => ' | ',
00611 ),
00612 (array)$options);
00613
00614 $params = array_merge(array('page'=> 1), (array)$this->params($options['model']));
00615 unset($options['model']);
00616
00617 if ($params['pageCount'] <= 1) {
00618 return false;
00619 }
00620
00621 extract($options);
00622 unset($options['tag'], $options['before'], $options['model'], $options['separator']);
00623
00624 $out = '';
00625 $lower = $params['pageCount'] - $last + 1;
00626
00627 if (is_int($last) && $params['page'] < $lower) {
00628 if ($before === null) {
00629 $before = '...';
00630 }
00631 for ($i = $lower; $i <= $params['pageCount']; $i++) {
00632 $out .= $this->Html->tag($tag, $this->link($i, array('page' => $i), $options));
00633 if ($i != $params['pageCount']) {
00634 $out .= $separator;
00635 }
00636 }
00637 $out = $before . $out;
00638 } elseif ($params['page'] < $params['pageCount']) {
00639 $out = $before . $this->Html->tag($tag, $this->link($last, array('page' => $params['pageCount']), $options));
00640 }
00641 return $out;
00642 }
00643 }
00644 ?>