Re-adding ability to order by virtual fields in DboSource::order

Adding support for paginating virtual model fields in controller
This commit is contained in:
José Lorenzo Rodríguez 2009-12-06 02:10:33 -04:30
parent 051d352eab
commit cf359a38b3
3 changed files with 40 additions and 96 deletions

View file

@ -1076,9 +1076,11 @@ class Controller extends Object {
$value = $options['order'][$key];
unset($options['order'][$key]);
if (isset($object->{$alias}) && $object->{$alias}->hasField($field)) {
if ($object->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
} elseif ($object->hasField($field)) {
} elseif ($object->hasField($field,true)) {
$options['order'][$field] = $value;
} elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field)) {
$options['order'][$alias . '.' . $field] = $value;
}
}

View file

@ -2216,6 +2216,14 @@ class DboSource extends DataSource {
return null;
}
/**
* Returns an ORDER BY clause as a string.
*
* @param string $key Field reference, as a key (i.e. Post.title)
* @param string $direction Direction (ASC or DESC)
* @param object $model model reference (used to look for virtual field)
* @return string ORDER BY clause
*/
function order($keys, $direction = 'ASC', &$model = null) {
if (!is_array($keys)) {
$keys = array($keys);
@ -2246,7 +2254,7 @@ class DboSource extends DataSource {
}
continue;
}
if (preg_match('/\\x20ASC|\\x20DESC/i', $key, $_dir)) {
$dir = $_dir[0];
$key = preg_replace('/\\x20ASC|\\x20DESC/i', '', $key);
@ -2264,7 +2272,11 @@ class DboSource extends DataSource {
$key = trim($key);
if (!preg_match('/\s/', $key) && !strpos($key,'.')) {
$key = $this->name($key);
if (!empty($model->virtualFields[$key])) {
$key = $model->virtualFields[$key];
} else {
$key = $this->name($key);
}
}
$key .= ' ' . trim($dir);
$result[] = $key;
@ -2275,79 +2287,6 @@ class DboSource extends DataSource {
return '';
}
/**
* Returns an ORDER BY clause as a string.
*
* @param string $key Field reference, as a key (i.e. Post.title)
* @param string $direction Direction (ASC or DESC)
* @param object $model model reference (used to look for virtual field)
* @return string ORDER BY clause
*/
function order2($keys, $direction = 'ASC', &$model = null) {
if (is_string($keys) && !empty($model->virtualFields[$keys])) {
return '(' . $model->virtualFields[$keys] . ') ' . $direction;
}
if (is_string($keys) && strpos($keys, ',') && !preg_match('/\(.+\,.+\)/', $keys)) {
$keys = array_map('trim', explode(',', $keys));
}
if (is_array($keys)) {
$keys = array_filter($keys);
$dir = $direction;
}
if (empty($keys) || (is_array($keys) && isset($keys[0]) && empty($keys[0]))) {
return '';
}
if (is_array($keys)) {
foreach ($keys as $key => $value) {
if (is_numeric($key)) {
$key = $value = ltrim(str_replace('ORDER BY ', '', $this->order($value,'ASC',$model)));
$value = (!preg_match('/\\x20ASC|\\x20DESC/i', $key) ? ' ' . $direction : '');
} else {
$value = ' ' . $value;
}
if (!preg_match('/^.+\\(.*\\)/', $key) && !strpos($key, ',')) {
if (preg_match('/\\x20ASC|\\x20DESC/i', $key, $dir)) {
$dir = $dir[0];
$key = preg_replace('/\\x20ASC|\\x20DESC/i', '', $key);
} else {
$dir = '';
}
$key = trim($key);
if (!preg_match('/\s/', $key)) {
$key = $this->name($key);
}
$key .= ' ' . trim($dir);
}
$order[] = $this->order($key . $value,'ASC',$model);
}
return ' ORDER BY ' . trim(str_replace('ORDER BY', '', implode(',', $order)));
}
$keys = preg_replace('/ORDER\\x20BY/i', '', $keys);
if (strpos($keys, '.')) {
preg_match_all('/([a-zA-Z0-9_]{1,})\\.([a-zA-Z0-9_]{1,})/', $keys, $result, PREG_PATTERN_ORDER);
$pregCount = count($result[0]);
for ($i = 0; $i < $pregCount; $i++) {
if (!is_numeric($result[0][$i])) {
$keys = preg_replace('/' . $result[0][$i] . '/', $this->name($result[0][$i]), $keys);
}
}
$result = ' ORDER BY ' . $keys;
return $result . (!preg_match('/\\x20ASC|\\x20DESC/i', $keys) ? ' ' . $direction : '');
} elseif (preg_match('/(\\x20ASC|\\x20DESC)/i', $keys, $match)) {
$direction = $match[1];
return ' ORDER BY ' . preg_replace('/' . $match[1] . '/', '', $keys) . $direction;
}
return ' ORDER BY ' . $keys . ' ' . $direction;
}
/**
* Create a GROUP BY SQL clause
*

View file

@ -418,25 +418,6 @@ class ControllerTest extends CakeTestCase {
App::build();
}
function testPaginateOrderVirtualField() {
$Controller =& new Controller();
$Controller->uses = array('ControllerPost', 'ControllerComment');
$Controller->passedArgs[] = '1';
$Controller->params['url'] = array();
$Controller->constructClasses();
$Controller->ControllerPost->virtualFields = array('offset_test' => 'ControllerPost.id + 1');
$Controller->paginate = array(
'fields' => array('id', 'title'),
'order' => 'offset_test',
'limit' => 1
);
$result = $Controller->paginate('ControllerPost');
$this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(2, 3));
exit;
}
/**
* testConstructClasses method
*
@ -1262,5 +1243,27 @@ class ControllerTest extends CakeTestCase {
$this->assertEqual($Controller->RequestHandler->prefers(), 'rss');
unset($Controller);
}
function testPaginateOrderVirtualField() {
$Controller =& new Controller();
$Controller->uses = array('ControllerPost', 'ControllerComment');
$Controller->passedArgs[] = '1';
$Controller->params['url'] = array();
$Controller->constructClasses();
$Controller->ControllerPost->virtualFields = array(
'offset_test' => 'ControllerPost.id + 1'
);
$Controller->paginate = array(
'fields' => array('id', 'title','offset_test'),
'order' => array('offset_test' => 'DESC')
);
$result = $Controller->paginate('ControllerPost');
$this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(4,3,2));
$Controller->passedArgs = array('sort' => 'offset_test', 'direction' => 'asc');
$result = $Controller->paginate('ControllerPost');
$this->assertEqual(Set::extract($result, '{n}.ControllerPost.offset_test'), array(2,3,4));
}
}
?>