Moving validation of sorting to a separate method. This makes it easier to test, extends and read.

Tests added.
This commit is contained in:
mark_story 2010-12-19 02:11:39 -05:00
parent 7b11eeb6e0
commit 108a6611a8
2 changed files with 86 additions and 31 deletions

View file

@ -95,41 +95,12 @@ class PaginatorComponent extends Component {
throw new MissingModelException($object);
}
$options = $this->mergeOptions($object->alias, $scope, $whitelist);
if (isset($options['show'])) {
$options['limit'] = $options['show'];
}
if (isset($options['sort'])) {
$direction = null;
if (isset($options['direction'])) {
$direction = strtolower($options['direction']);
}
if ($direction != 'asc' && $direction != 'desc') {
$direction = 'asc';
}
$options['order'] = array($options['sort'] => $direction);
}
if (!empty($options['order']) && is_array($options['order'])) {
$alias = $object->alias ;
$key = $field = key($options['order']);
if (strpos($key, '.') !== false) {
list($alias, $field) = explode('.', $key);
}
$value = $options['order'][$key];
unset($options['order'][$key]);
if ($object->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
} elseif ($object->hasField($field, true)) {
$options['order'][$field] = $value;
} elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
}
}
$options = $this->mergeOptions($object->alias, $scope, $whitelist);
$options = $this->validateSort($object, $options);
$conditions = $fields = $order = $limit = $page = $recursive = null;
@ -312,4 +283,47 @@ class PaginatorComponent extends Component {
return array_merge($defaults, $request, $options);
}
/**
* Validate that the desired sorting can be performed on the $object. Only fields or
* virtualFields can be sorted on. The direction param will also be sanitized. Lastly
* sort + direction keys will be converted into the model friendly order key.
*
* @param Model $object The model being paginated.
* @param array $options The pagination options being used for this request.
* @return array An array of options with sort + direction removed and replaced with order if possible.
*/
public function validateSort($object, $options) {
if (isset($options['sort'])) {
$direction = null;
if (isset($options['direction'])) {
$direction = strtolower($options['direction']);
}
if ($direction != 'asc' && $direction != 'desc') {
$direction = 'asc';
}
$options['order'] = array($options['sort'] => $direction);
}
if (!empty($options['order']) && is_array($options['order'])) {
$alias = $object->alias ;
$key = $field = key($options['order']);
if (strpos($key, '.') !== false) {
list($alias, $field) = explode('.', $key);
}
$value = $options['order'][$key];
unset($options['order'][$key]);
if ($object->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
} elseif ($object->hasField($field, true)) {
$options['order'][$field] = $value;
} elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
}
}
return $options;
}
}

View file

@ -696,4 +696,45 @@ class PaginatorTest extends CakeTestCase {
);
$this->assertEquals($expected, $result);
}
/**
* test that invalid directions are ignored.
*
* @return void
*/
function testValidateSortInvalidDirection() {
$model = $this->getMock('Model');
$model->alias = 'model';
$model->expects($this->any())->method('hasField')->will($this->returnValue(true));
$options = array('sort' => 'something', 'direction' => 'boogers');
$result = $this->Paginator->validateSort($model, $options);
$this->assertEquals('asc', $result['order']['model.something']);
}
/**
* test that virtual fields work.
*
* @return void
*/
function testValidateSortVirtualField() {
$model = $this->getMock('Model');
$model->alias = 'model';
$model->expects($this->at(0))
->method('hasField')
->with('something')
->will($this->returnValue(false));
$model->expects($this->at(1))
->method('hasField')
->with('something', true)
->will($this->returnValue(true));
$options = array('sort' => 'something', 'direction' => 'desc');
$result = $this->Paginator->validateSort($model, $options);
$this->assertEquals('desc', $result['order']['something']);
}
}