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