Merge branch 'virtual-fields' into 1.3-misc

Conflicts:
	cake/tests/cases/libs/controller/controller.test.php
This commit is contained in:
Mark Story 2009-12-19 19:40:12 -05:00
commit 4ac0a55aff
6 changed files with 436 additions and 72 deletions
cake
libs
controller
model
tests/cases/libs

View file

@ -1102,9 +1102,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

@ -363,6 +363,9 @@ class DboSource extends DataSource {
if ($this->hasResult()) {
$this->resultSet($this->_result);
$resultRow = $this->fetchResult();
if (!empty($resultRow)) {
$this->fetchVirtualField($resultRow);
}
return $resultRow;
} else {
return null;
@ -393,6 +396,7 @@ class DboSource extends DataSource {
$out[] = $first;
}
while ($this->hasResult() && $item = $this->fetchResult()) {
$this->fetchVirtualField($item);
$out[] = $item;
}
@ -410,6 +414,35 @@ class DboSource extends DataSource {
}
}
/**
* Modifies $result array to place virtual fields in model entry where they belongs to
*
* @param array $resut REference to the fetched row
* @return void
*/
function fetchVirtualField(&$result) {
if (isset($result[0]) && is_array($result[0])) {
foreach ($result[0] as $field => $value) {
if (strpos($field, '__') === false) {
continue;
}
list($alias, $virtual) = explode('__', $field);
if (!ClassRegistry::isKeySet($alias)) {
return;
}
$model = ClassRegistry::getObject($alias);
if ($model->isVirtualField($virtual)) {
$result[$alias][$virtual] = $value;
unset($result[0][$field]);
}
}
if (empty($result[0])) {
unset($result[0]);
}
}
}
/**
* Returns a single field of the first of query results for a given SQL query, or false if empty.
*
@ -420,7 +453,6 @@ class DboSource extends DataSource {
*/
function field($name, $sql) {
$data = $this->fetchRow($sql);
if (!isset($data[$name]) || empty($data[$name])) {
return false;
} else {
@ -1363,7 +1395,7 @@ class DboSource extends DataSource {
* @access public
* @see DboSource::renderStatement()
*/
function buildStatement($query, $model) {
function buildStatement($query, &$model) {
$query = array_merge(array('offset' => null, 'joins' => array()), $query);
if (!empty($query['joins'])) {
$count = count($query['joins']);
@ -1378,7 +1410,7 @@ class DboSource extends DataSource {
'fields' => implode(', ', $query['fields']),
'table' => $query['table'],
'alias' => $this->alias . $this->name($query['alias']),
'order' => $this->order($query['order']),
'order' => $this->order($query['order'], 'ASC', $model),
'limit' => $this->limit($query['limit'], $query['offset']),
'joins' => implode(' ', $query['joins']),
'group' => $this->group($query['group'])
@ -1657,13 +1689,23 @@ class DboSource extends DataSource {
if (!isset($params[1])) {
$params[1] = 'count';
}
return 'COUNT(' . $this->name($params[0]) . ') AS ' . $this->name($params[1]);
if (is_object($model) && $model->isVirtualField($params[0])){
$arg = $this->__quoteFields($model->getVirtualField($params[0]));
} else {
$arg = $this->name($params[0]);
}
return 'COUNT(' . $arg . ') AS ' . $this->name($params[1]);
case 'max':
case 'min':
if (!isset($params[1])) {
$params[1] = $params[0];
}
return strtoupper($func) . '(' . $this->name($params[0]) . ') AS ' . $this->name($params[1]);
if (is_object($model) && $model->isVirtualField($params[0])) {
$arg = $this->__quoteFields($model->getVirtualField($params[0]));
} else {
$arg = $this->name($params[0]);
}
return strtoupper($func) . '(' . $arg . ') AS ' . $this->name($params[1]);
break;
}
}
@ -1790,6 +1832,24 @@ class DboSource extends DataSource {
return $data;
}
/**
* Converts model virtual fields into sql expressions to be fetched later
*
* @param Model $model
* @param string $alias Alias tablename
* @param mixed $fields virtual fields to be used on query
* @return array
*/
function _constructVirtualFields(&$model,$alias,$fields) {
$virtual = array();
foreach ($fields as $field) {
$virtualField = $this->name("{$alias}__{$field}");
$expression = $this->__quoteFields($model->getVirtualField($field));
$virtual[] = '(' .$expression . ") {$this->alias} {$virtualField}";
}
return $virtual;
}
/**
* Generates the fields list of an SQL query.
*
@ -1804,7 +1864,8 @@ class DboSource extends DataSource {
if (empty($alias)) {
$alias = $model->alias;
}
if (empty($fields)) {
$allFields = empty($fields);
if ($allFields) {
$fields = array_keys($model->schema());
} elseif (!is_array($fields)) {
$fields = String::tokenize($fields);
@ -1814,10 +1875,19 @@ class DboSource extends DataSource {
if (!$quote) {
return $fields;
}
$virtual = array();
if ($model->getVirtualField()) {
$keys = array_keys($model->getVirtualField());
$virtual = ($allFields) ? $keys : array_intersect($keys, $fields);
}
$count = count($fields);
if ($count >= 1 && !in_array($fields[0], array('*', 'COUNT(*)'))) {
for ($i = 0; $i < $count; $i++) {
if (in_array($fields[$i], $virtual)) {
unset($fields[$i]);
continue;
}
if (preg_match('/^\(.*\)\s' . $this->alias . '.*/i', $fields[$i])){
continue;
} elseif (!preg_match('/^.+\\(.*\\)/', $fields[$i])) {
@ -1871,6 +1941,9 @@ class DboSource extends DataSource {
}
}
}
if (!empty($virtual)) {
$fields = array_merge($fields,$this->_constructVirtualFields($model, $alias, $virtual));
}
return array_unique($fields);
}
@ -2053,6 +2126,11 @@ class DboSource extends DataSource {
}
}
$virtual = false;
if (is_object($model) && $model->isVirtualField($key)) {
$key = $this->__quoteFields($model->getVirtualField($key));
$virtual = true;
}
$type = (is_object($model) ? $model->getColumnType($key) : null);
@ -2067,7 +2145,7 @@ class DboSource extends DataSource {
$value = $this->value($value, $type);
if ($key !== '?') {
if (!$virtual && $key !== '?') {
$isKey = (strpos($key, '(') !== false || strpos($key, ')') !== false);
$key = $isKey ? $this->__quoteFields($key) : $this->name($key);
}
@ -2105,7 +2183,9 @@ class DboSource extends DataSource {
break;
}
}
if ($virtual) {
return "({$key}) {$operator} {$value}";
}
return "{$key} {$operator} {$value}";
}
@ -2172,69 +2252,71 @@ class DboSource extends DataSource {
*
* @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
* @access public
*/
function order($keys, $direction = 'ASC') {
if (is_string($keys) && strpos($keys, ',') && !preg_match('/\(.+\,.+\)/', $keys)) {
$keys = array_map('trim', explode(',', $keys));
function order($keys, $direction = 'ASC', &$model = null) {
if (!is_array($keys)) {
$keys = array($keys);
}
$keys = array_filter($keys);
$result = array();
while (!empty($keys)) {
list($key, $dir) = each($keys);
array_shift($keys);
if (is_array($keys)) {
$keys = array_filter($keys);
}
if (is_numeric($key)) {
$key = $dir;
$dir = $direction;
}
if (empty($keys) || (is_array($keys) && isset($keys[0]) && empty($keys[0]))) {
return '';
}
if (is_array($keys)) {
$keys = (Set::countDim($keys) > 1) ? array_map(array(&$this, 'order'), $keys) : $keys;
foreach ($keys as $key => $value) {
if (is_numeric($key)) {
$key = $value = ltrim(str_replace('ORDER BY ', '', $this->order($value)));
$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);
if (is_string($key) && strpos($key, ',') && !preg_match('/\(.+\,.+\)/', $key)) {
$key = array_map('trim', explode(',', $key));
}
if (is_array($key)) {
//Flatten the array
$key = array_reverse($key, true);
foreach ($key as $k => $v) {
if (is_numeric($k)) {
array_unshift($keys, $v);
} else {
$dir = '';
$keys = array($k => $v) + $keys;
}
$key = trim($key);
if (!preg_match('/\s/', $key)) {
$key = $this->name($key);
}
$key .= ' ' . trim($dir);
}
$order[] = $this->order($key . $value);
continue;
}
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]);
if (preg_match('/\\x20ASC|\\x20DESC/i', $key, $_dir)) {
$dir = $_dir[0];
$key = preg_replace('/\\x20ASC|\\x20DESC/i', '', $key);
}
for ($i = 0; $i < $pregCount; $i++) {
if (!is_numeric($result[0][$i])) {
$keys = preg_replace('/' . $result[0][$i] . '/', $this->name($result[0][$i]), $keys);
if (strpos($key, '.')) {
preg_match_all('/([a-zA-Z0-9_]{1,})\\.([a-zA-Z0-9_]{1,})/', $key, $matches, PREG_PATTERN_ORDER);
$pregCount = count($matches[0]);
for ($i = 0; $i < $pregCount; $i++) {
if (!is_numeric($matches[0][$i])) {
$key = preg_replace('/' . $matches[0][$i] . '/', $this->name($matches[0][$i]), $key);
}
}
}
$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;
$key = trim($key);
if (!preg_match('/\s/', $key) && !strpos($key,'.')) {
if (is_object($model) && $model->isVirtualField($key)) {
$key = '('.$this->__quoteFields($model->getVirtualField($key)).')';
} else {
$key = $this->name($key);
}
}
$key .= ' ' . trim($dir);
$result[] = $key;
}
return ' ORDER BY ' . $keys . ' ' . $direction;
if (!empty($result)) {
return ' ORDER BY ' . implode(', ', $result);
}
return '';
}
/**

View file

@ -802,7 +802,7 @@ class Model extends Overloadable {
}
/**
* This function does two things:
* This function does two things:
*
* 1. it scans the array $one for the primary key,
* and if that's found, it sets the current id to the value of $one[id].
@ -1009,21 +1009,28 @@ class Model extends Overloadable {
* Returns true if the supplied field exists in the model's database table.
*
* @param mixed $name Name of field to look for, or an array of names
* @param boolean $checkVirtual checks if the field is declared as virtual
* @return mixed If $name is a string, returns a boolean indicating whether the field exists.
* If $name is an array of field names, returns the first field that exists,
* or false if none exist.
* @access public
*/
function hasField($name) {
function hasField($name, $checkVirtual = false) {
if (is_array($name)) {
foreach ($name as $n) {
if ($this->hasField($n)) {
if ($this->hasField($n, $checkVirtual)) {
return $n;
}
}
return false;
}
if ($checkVirtual && !empty($this->virtualFields)) {
if ($this->isVirtualField($name)) {
return true;
}
}
if (empty($this->_schema)) {
$this->schema();
}
@ -1034,9 +1041,39 @@ class Model extends Overloadable {
return false;
}
/**
* Returns true if the supplied field is a model Virtual Field
*
* @param mixed $name Name of field to look for
* @return boolean indicating whether the field exists as a model virtual field.
* @access public
*/
function isVirtualField($field) {
return !empty($this->virtualFields) && is_string($field) && array_key_exists($field, $this->virtualFields);
}
/**
* Returns the expression for a model virtual field
*
* @param mixed $name Name of field to look for
* @return mixed If $field is string expression bound to virtual field $field
* If $field is null, returns an array of all model virtual fields
* or false if none $field exist.
* @access public
*/
function getVirtualField($field = null) {
if ($field == null) {
return empty($this->virtualFields) ? false : $this->virtualFields;
}
if ($this->isVirtualField($field)) {
return $this->virtualFields[$field];
}
return false;
}
/**
* Initializes the model for writing a new record, loading the default values
* for those fields that are not defined in $data, and clearing previous validation errors.
* for those fields that are not defined in $data, and clearing previous validation errors.
* Especially helpful for saving data in loops.
*
* @param mixed $data Optional data array to assign to the model after it is created. If null or false,
@ -1121,7 +1158,8 @@ class Model extends Overloadable {
} else {
$recursive = $this->recursive;
}
if ($data = $this->find($conditions, $name, $order, $recursive)) {
$fields = $name;
if ($data = $this->find('first', compact('conditions', 'fields', 'order', 'recursive'))) {
if (strpos($name, '.') === false) {
if (isset($data[$this->alias][$name])) {
return $data[$this->alias][$name];
@ -1132,9 +1170,8 @@ class Model extends Overloadable {
return $data[$name[0]][$name[1]];
}
}
if (!empty($data[0])) {
$name = key($data[0]);
return $data[0][$name];
if (isset($data[0]) && count($data[0]) > 0) {
return array_shift($data[0]);
}
} else {
return false;
@ -1989,7 +2026,7 @@ class Model extends Overloadable {
* second parameter options for finding ( indexed array, including: 'conditions', 'limit',
* 'recursive', 'page', 'fields', 'offset', 'order')
*
* Eg:
* Eg:
* {{{
* find('all', array(
* 'conditions' => array('name' => 'Thomas Anderson'),
@ -2560,7 +2597,7 @@ class Model extends Overloadable {
$valid = preg_match($rule, $data[$fieldName]);
} elseif (Configure::read('debug') > 0) {
$error = sprintf(
__('Could not find validation handler %s for %s', true),
__('Could not find validation handler %s for %s', true),
$rule,
$fieldName
);

View file

@ -1281,5 +1281,26 @@ class ControllerTest extends CakeTestCase {
$expected = array(404 => 'Sorry Bro');
$this->assertEqual($result, $expected);
}
function testPaginateOrderVirtualField() {
$Controller =& new Controller();
$Controller->uses = array('ControllerPost', 'ControllerComment');
$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));
}
}
?>

View file

@ -3403,7 +3403,7 @@ class DboSourceTest extends CakeTestCase {
$this->assertPattern('/^\s*ORDER BY\s+`title`\s+ASC\s*$/', $result);
$result = $this->testDb->order("Dealer.id = 7 desc, Dealer.id = 3 desc, Dealer.title asc");
$expected = " ORDER BY `Dealer`.`id` = 7 desc, `Dealer`.`id` = 3 desc, `Dealer`.`title` asc";
$expected = " ORDER BY `Dealer`.`id` = 7 desc, `Dealer`.`id` = 3 desc, `Dealer`.`title` asc";
$this->assertEqual($result, $expected);
$result = $this->testDb->order(array("Page.name" => "='test' DESC"));
@ -3609,8 +3609,8 @@ class DboSourceTest extends CakeTestCase {
$this->testDb->fieldParameters['param'] = array(
'value' => 'COLLATE',
'quote' => false,
'join' => ' ',
'column' => 'Collate',
'join' => ' ',
'column' => 'Collate',
'position' => 'beforeDefault',
'options' => array('GOOD', 'OK')
);
@ -4081,5 +4081,147 @@ class DboSourceTest extends CakeTestCase {
$this->assertNoPattern('/Num:/s', $contents);
$this->assertNoPattern('/Took:/s', $contents);
}
/**
* test fields generating usable virtual fields to use in query
*
* @return void
*/
function testVirtualFields() {
$this->loadFixtures('Article');
$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments') . '.article_id'
);
$result = $this->db->fields($Article);
$expected = array(
'`Article`.`id`',
'`Article`.`user_id`',
'`Article`.`title`',
'`Article`.`body`',
'`Article`.`published`',
'`Article`.`created`',
'`Article`.`updated`',
'(NOW()) AS `Article__this_moment`',
'(1 + 1) AS `Article__two`',
'(SELECT COUNT(*) FROM comments WHERE `Article`.`id` = `comments`.`article_id`) AS `Article__comment_count`'
);
$this->assertEqual($expected,$result);
$result = $this->db->fields($Article, null, array('this_moment','title'));
$expected = array(
'`Article`.`title`',
'(NOW()) AS `Article__this_moment`',
);
$this->assertEqual($expected,$result);
}
/**
* test conditions to generate query conditions for virtual fields
*
* @return void
*/
function testVirtualFieldsInConditions() {
$this->loadFixtures('Article');
$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments') . '.article_id'
);
$conditions = array('two' => 2);
$result = $this->db->conditions($conditions,true,false,$Article);
$expected = '(1 + 1) = 2';
$this->assertEqual($expected, $result);
$conditions = array('this_moment BETWEEN ? AND ?' => array(1,2));
$expected = 'NOW() BETWEEN 1 AND 2';
$result = $this->db->conditions($conditions, true, false, $Article);
$this->assertEqual($expected, $result);
$conditions = array('comment_count >' => 5);
$expected = '(SELECT COUNT(*) FROM comments WHERE `Article`.`id` = `comments`.`article_id`) > 5';
$result = $this->db->conditions($conditions, true, false, $Article);
$this->assertEqual($expected, $result);
$conditions = array('NOT' => array('two' => 2));
$result = $this->db->conditions($conditions, true, false, $Article);
$expected = 'NOT ((1 + 1) = 2)';
$this->assertEqual($expected, $result);
}
/**
* test order to generate query order clause for virtual fields
*
* @return void
*/
function testVirtualFieldsInOrder() {
$this->loadFixtures('Article');
$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
);
$order = array('two', 'this_moment');
$result = $this->db->order($order, 'ASC', $Article);
$expected = ' ORDER BY (1 + 1) ASC, (NOW()) ASC';
$this->assertEqual($expected, $result);
}
/**
* test calculate to generate claculate statements on virtual fields
*
* @return void
*/
function testVirtualFieldsInCalculate() {
$this->loadFixtures('Article');
$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'this_moment' => 'NOW()',
'two' => '1 + 1',
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments'). '.article_id'
);
$result = $this->db->calculate($Article, 'count', array('this_moment'));
$expected = 'COUNT(NOW()) AS `count`';
$this->assertEqual($expected, $result);
$result = $this->db->calculate($Article, 'max', array('comment_count'));
$expected = 'MAX(SELECT COUNT(*) FROM comments WHERE `Article`.`id` = `comments`.`article_id`) AS `comment_count`';
$this->assertEqual($expected, $result);
}
/**
* test a full example of using virtual fields
*
* @return void
*/
function testVirtualFieldsFetch() {
$this->loadFixtures('Article', 'Comment');
$Article =& ClassRegistry::init('Article');
$Article->virtualFields = array(
'comment_count' => 'SELECT COUNT(*) FROM ' . $this->db->fullTableName('comments') .
' WHERE Article.id = ' . $this->db->fullTableName('comments') . '.article_id'
);
$conditions = array('comment_count >' => 2);
$query = 'SELECT ' . join(',',$this->db->fields($Article, null, array('id', 'comment_count'))) .
' FROM ' . $this->db->fullTableName($Article) . ' Article ' . $this->db->conditions($conditions, true, true, $Article);
$result = $this->db->fetchAll($query);
$expected = array(array(
'Article' => array('id' => 1, 'comment_count' => 4)
));
$this->assertEqual($expected, $result);
}
}
?>

View file

@ -215,14 +215,14 @@ class ModelReadTest extends BaseModelTest {
array('Product' => array('type' => 'Toy'), array('price' => 3))
);
$result = $Product->find('all',array(
'fields'=>array('Product.type','MIN(Product.price) as price'),
'fields'=>array('Product.type', 'MIN(Product.price) as price'),
'group'=> 'Product.type',
'order' => 'Product.type ASC'
));
$this->assertEqual($result, $expected);
$result = $Product->find('all', array(
'fields'=>array('Product.type','MIN(Product.price) as price'),
'fields'=>array('Product.type', 'MIN(Product.price) as price'),
'group'=> array('Product.type'),
'order' => 'Product.type ASC'));
$this->assertEqual($result, $expected);
@ -7161,5 +7161,85 @@ class ModelReadTest extends BaseModelTest {
$comments = $Comment->find('first');
$this->assertEqual($comments['Comment']['querytype'], 'first');
}
/**
* testVirtualFields()
*
* Test correct fetching of virtual fields
* currently is not possible to do Relation.virtualField
*
* @access public
* @return void
*/
function testVirtualFields() {
$this->loadFixtures('Post','Author');
$Post = ClassRegistry::init('Post');
$Post->virtualFields = array('two' => "1 + 1");
$result = $Post->find('first');
$this->assertEqual($result['Post']['two'], 2);
$Post->Author->virtualFields = array('false' => '1 = 2');
$result = $Post->find('first');
$this->assertEqual($result['Post']['two'], 2);
$this->assertEqual($result['Author']['false'],false);
$result = $Post->find('first',array('fields' => array('author_id')));
$this->assertFalse(isset($result['Post']['two']));
$this->assertFalse(isset($result['Author']['false']));
$result = $Post->find('first',array('fields' => array('author_id', 'two')));
$this->assertEqual($result['Post']['two'], 2);
$this->assertFalse(isset($result['Author']['false']));
$result = $Post->find('first',array('fields' => array('two')));
$this->assertEqual($result['Post']['two'], 2);
$Post->id = 1;
$result = $Post->field('two');
$this->assertEqual($result, 2);
$result = $Post->find('first',array(
'conditions' => array('two' => 2),
'limit' => 1
));
$this->assertEqual($result['Post']['two'], 2);
$result = $Post->find('first',array(
'conditions' => array('two <' => 3),
'limit' => 1
));
$this->assertEqual($result['Post']['two'], 2);
$result = $Post->find('first',array(
'conditions' => array('NOT' => array('two >' => 3)),
'limit' => 1
));
$this->assertEqual($result['Post']['two'], 2);
$dbo =& $Post->getDataSource();
$Post->virtualFields = array('other_field' => 'Post.id + 1');
$result = $Post->find('first',array(
'conditions' => array('other_field' => 3),
'limit' => 1
));
$this->assertEqual($result['Post']['id'], 2);
$Post->virtualFields = array('other_field' => 'Post.id + 1');
$result = $Post->find('all',array(
'fields' => array($dbo->calculate($Post, 'max',array('other_field')))
));
$this->assertEqual($result[0][0]['other_field'], 4);
ClassRegistry::flush();
$Writing = ClassRegistry::init(array('class' => 'Post', 'alias' => 'Writing'), 'Model');
$Writing->virtualFields = array('two' => "1 + 1");
$result = $Writing->find('first');
$this->assertEqual($result['Writing']['two'], 2);
$Post->create();
$Post->virtualFields = array('other_field' => 'COUNT(Post.id) + 1');
$result = $Post->field('other_field');
$this->assertEqual($result, 4);
}
}
?>