Skip to content

Commit

Permalink
Fix Controller::paginate and ordering with virtualFields.
Browse files Browse the repository at this point in the history
Model::isVirtualField() does ensure that model names match the current model.
This creates false positives when doing sorting datasets when an associated
model has a field with the same name as a virtualField.
Fixes #1822. Fixes #1756.
  • Loading branch information
markstory committed Oct 5, 2011
1 parent 499b5e7 commit a6e4208
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 3 deletions.
4 changes: 2 additions & 2 deletions cake/libs/controller/controller.php
Expand Up @@ -1126,7 +1126,7 @@ function paginate($object = null, $scope = array(), $whitelist = array()) {
}

if (!empty($options['order']) && is_array($options['order'])) {
$alias = $object->alias ;
$alias = $object->alias;
$key = $field = key($options['order']);

if (strpos($key, '.') !== false) {
Expand All @@ -1137,7 +1137,7 @@ function paginate($object = null, $scope = array(), $whitelist = array()) {

if ($object->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
} elseif ($object->hasField($field, true)) {
} elseif ($object->hasField($key, true)) {
$options['order'][$field] = $value;
} elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
Expand Down
2 changes: 1 addition & 1 deletion cake/libs/model/model.php
Expand Up @@ -1037,7 +1037,7 @@ function isVirtualField($field) {
}
if (strpos($field, '.') !== false) {
list($model, $field) = explode('.', $field);
if (isset($this->virtualFields[$field])) {
if ($model == $this->alias && isset($this->virtualFields[$field])) {
return true;
}
}
Expand Down
30 changes: 30 additions & 0 deletions cake/tests/cases/libs/controller/controller.test.php
Expand Up @@ -832,6 +832,36 @@ function testPaginateOrderVirtualField() {
$this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(2, 3, 4));
}

/**
* test paginate() and virtualField overlapping with real fields.
*
* @return void
*/
function testPaginateOrderVirtualFieldSharedWithRealField() {
$Controller =& new Controller();
$Controller->uses = array('ControllerPost', 'ControllerComment');
$Controller->params['url'] = array();
$Controller->constructClasses();
$Controller->ControllerComment->virtualFields = array(
'title' => 'ControllerComment.comment'
);
$Controller->ControllerComment->bindModel(array(
'belongsTo' => array(
'ControllerPost' => array(
'className' => 'ControllerPost',
'foreignKey' => 'article_id'
)
)
), false);

$Controller->paginate = array(
'fields' => array('ControllerComment.id', 'title', 'ControllerPost.title'),
);
$Controller->passedArgs = array('sort' => 'ControllerPost.title', 'dir' => 'asc');
$result = $Controller->paginate('ControllerComment');
$this->assertEqual(Set::extract($result, '{n}.ControllerComment.id'), array(1, 2, 3, 4, 5, 6));
}

/**
* testFlash method
*
Expand Down
1 change: 1 addition & 0 deletions cake/tests/cases/libs/model/model_read.test.php
Expand Up @@ -7435,6 +7435,7 @@ function testIsVirtualField() {

$this->assertTrue($Post->isVirtualField('other_field'));
$this->assertTrue($Post->isVirtualField('Post.other_field'));
$this->assertFalse($Post->isVirtualField('Comment.other_field'), 'Other models should not match.');
$this->assertFalse($Post->isVirtualField('id'));
$this->assertFalse($Post->isVirtualField('Post.id'));
$this->assertFalse($Post->isVirtualField(array()));
Expand Down

0 comments on commit a6e4208

Please sign in to comment.