Skip to content

Commit 2292838

Browse files
committed
Make request property lazy loaded & fix most sorting issues.
Make the request object access happen only when it is required instead of during the constructor. Remove automagic detection of associated fields and virtual fields (which don't exist yet). If you need to sort on associated fields, you will need to use the whitelist features. CakePHP will only check the primary table being pagintaed for columns. This keeps the magic to a minimum and still affords prototyping.
1 parent 7dd9bea commit 2292838

File tree

2 files changed

+27
-59
lines changed

2 files changed

+27
-59
lines changed

Cake/Controller/Component/PaginatorComponent.php

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,6 @@
3131
*/
3232
class PaginatorComponent extends Component {
3333

34-
/**
35-
* The current request instance.
36-
*
37-
* @var Cake\Network\Request
38-
*/
39-
public $request;
40-
4134
/**
4235
* Default pagination settings.
4336
*
@@ -67,18 +60,6 @@ class PaginatorComponent extends Component {
6760
'limit', 'sort', 'page', 'direction'
6861
);
6962

70-
/**
71-
* Constructor
72-
*
73-
* @param ComponentRegistry $collection A ComponentRegistry this component can use to lazy load its components
74-
* @param array $settings Array of configuration settings.
75-
*/
76-
public function __construct(ComponentRegistry $collection, $settings = []) {
77-
$settings = array_merge($this->_defaultConfig, (array)$settings);
78-
$this->request = $collection->getController()->request;
79-
parent::__construct($collection, $settings);
80-
}
81-
8263
/**
8364
* Handles automatic pagination of model records.
8465
*
@@ -106,7 +87,7 @@ public function __construct(ComponentRegistry $collection, $settings = []) {
10687
* 'Articles' => [
10788
* 'limit' => 20,
10889
* 'maxLimit' => 100
109-
* [,
90+
* ],
11091
* 'Comments' => [ ... ]
11192
* ];
11293
* $results = $paginator->paginate($table, $settings);
@@ -142,9 +123,6 @@ public function paginate($object, $settings = array(), $whitelist = array()) {
142123
$alias = $object->alias();
143124

144125
$options = $this->mergeOptions($alias, $settings);
145-
146-
// TODO perhaps move this until after the query has been created.
147-
// Then we could look at the fields in the query.
148126
$options = $this->validateSort($object, $options, $whitelist);
149127
$options = $this->checkLimit($options);
150128

@@ -181,7 +159,6 @@ public function paginate($object, $settings = array(), $whitelist = array()) {
181159
$query = $object->find($type, array_merge($parameters, $extra));
182160

183161
// TODO Validate sort and apply them here.
184-
185162
$results = $query->execute();
186163
$numResults = count($results);
187164

@@ -192,7 +169,8 @@ public function paginate($object, $settings = array(), $whitelist = array()) {
192169
$count = 0;
193170
} else {
194171
$parameters = compact('conditions');
195-
$count = $object->find($type, array_merge($parameters, $extra))->count();
172+
$query = $object->find($type, array_merge($parameters, $extra));
173+
$count = $query->count();
196174
}
197175

198176
$pageCount = intval(ceil($count / $limit));
@@ -202,6 +180,8 @@ public function paginate($object, $settings = array(), $whitelist = array()) {
202180
throw new Error\NotFoundException();
203181
}
204182

183+
$request = $this->_registry->getController()->request;
184+
205185
if (!is_array($order)) {
206186
$order = (array)$order;
207187
}
@@ -219,11 +199,11 @@ public function paginate($object, $settings = array(), $whitelist = array()) {
219199
'limit' => $defaults['limit'] != $options['limit'] ? $options['limit'] : null,
220200
);
221201

222-
if (!isset($this->request['paging'])) {
223-
$this->request['paging'] = array();
202+
if (!isset($request['paging'])) {
203+
$request['paging'] = array();
224204
}
225-
$this->request['paging'] = array_merge(
226-
(array)$this->request['paging'],
205+
$request['paging'] = array_merge(
206+
(array)$request['paging'],
227207
array($alias => $paging)
228208
);
229209
return $results;
@@ -247,8 +227,8 @@ public function paginate($object, $settings = array(), $whitelist = array()) {
247227
*/
248228
public function mergeOptions($alias, $settings) {
249229
$defaults = $this->getDefaults($alias, $settings);
250-
$request = $this->request->query;
251-
$request = array_intersect_key($request, array_flip($this->whitelist));
230+
$request = $this->_registry->getController()->request;
231+
$request = array_intersect_key($request->query, array_flip($this->whitelist));
252232
return array_merge($defaults, $request);
253233
}
254234

@@ -302,26 +282,28 @@ public function validateSort(Table $object, array $options, array $whitelist = a
302282
}
303283
$options['order'] = array($options['sort'] => $direction);
304284
}
285+
unset($options['sort'], $options['direction']);
305286

306-
if (empty($options['order']) || (isset($options['order']) && is_array($options['order']))) {
307-
$options['order'] = null;
308-
return $options;
287+
if (empty($options['order'])) {
288+
$options['order'] = [];
289+
}
290+
if (!is_array($options['order'])) {
291+
$options['order'] = (array)$options['order'];
309292
}
310293

311294
if (!empty($whitelist)) {
312295
$field = key($options['order']);
313296
$inWhitelist = in_array($field, $whitelist, true);
314297
if (!$inWhitelist) {
315-
$options['order'] = null;
298+
$options['order'] = [];
316299
}
317300
return $options;
318301
}
319302

320-
if (!empty($options['order']) && is_array($options['order'])) {
303+
if (is_array($options['order'])) {
321304
$tableAlias = $object->alias();
322-
$order = array();
305+
$order = [];
323306

324-
// TODO Remove associated field checks and rely on the whitelist.
325307
foreach ($options['order'] as $key => $value) {
326308
$field = $key;
327309
$alias = $tableAlias;
@@ -332,16 +314,10 @@ public function validateSort(Table $object, array $options, array $whitelist = a
332314

333315
if ($correctAlias && $object->hasField($field)) {
334316
$order[$tableAlias . '.' . $field] = $value;
335-
} elseif ($correctAlias && $object->hasField($key, true)) {
336-
$order[$field] = $value;
337-
} elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field, true)) {
338-
// TODO fix associated sorting.
339-
$order[$alias . '.' . $field] = $value;
340317
}
341318
}
342319
$options['order'] = $order;
343320
}
344-
unset($options['sort'], $options['direction']);
345321

346322
return $options;
347323
}

Cake/Test/TestCase/Controller/Component/PaginatorComponentTest.php

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,7 @@ public function testPageParamCasting() {
8989
->will($this->returnValue('Posts'));
9090

9191
$query = $this->_getMockFindQuery();
92-
$this->Post->expects($this->at(1))
93-
->method('find')
94-
->will($this->returnValue($query));
95-
96-
$this->Post->expects($this->at(2))
92+
$this->Post->expects($this->any())
9793
->method('find')
9894
->will($this->returnValue($query));
9995

@@ -178,7 +174,7 @@ public function testPaginateCustomFinder() {
178174
*/
179175
public function testDefaultPaginateParams() {
180176
$settings = array(
181-
'order' => 'PaginatorPosts.id DESC',
177+
'order' => ['PaginatorPosts.id' => 'DESC'],
182178
'maxLimit' => 10,
183179
);
184180

@@ -192,7 +188,7 @@ public function testDefaultPaginateParams() {
192188
'fields' => null,
193189
'limit' => 10,
194190
'page' => 1,
195-
'order' => 'PaginatorPosts.id DESC'
191+
'order' => ['PaginatorPosts.id' => 'DESC']
196192
])
197193
->will($this->returnValue($query));
198194

@@ -496,7 +492,7 @@ public function testValidateSortWhitelistFailure() {
496492
$options = array('sort' => 'body', 'direction' => 'asc');
497493
$result = $this->Paginator->validateSort($model, $options, array('title', 'id'));
498494

499-
$this->assertNull($result['order']);
495+
$this->assertEquals([], $result['order']);
500496
}
501497

502498
/**
@@ -615,12 +611,7 @@ public function testValidateSortNoSort() {
615611

616612
$options = array('direction' => 'asc');
617613
$result = $this->Paginator->validateSort($model, $options, array('title', 'id'));
618-
$this->assertFalse(isset($result['order']));
619-
620-
$options = array('order' => 'invalid desc');
621-
$result = $this->Paginator->validateSort($model, $options, array('title', 'id'));
622-
623-
$this->assertEquals($options['order'], $result['order']);
614+
$this->assertEquals([], $result['order']);
624615
}
625616

626617
/**
@@ -877,8 +868,9 @@ protected function _getMockFindQuery() {
877868
->will($this->returnValue($results));
878869

879870
$query->expects($this->any())
880-
->method('total')
871+
->method('count')
881872
->will($this->returnValue(2));
873+
882874
return $query;
883875
}
884876

0 commit comments

Comments
 (0)