mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-03-28 12:42:58 +00:00
Merge branch 'virtual-fields' into 1.3-misc
Conflicts: cake/tests/cases/libs/controller/controller.test.php
This commit is contained in:
commit
4ac0a55aff
6 changed files with 436 additions and 72 deletions
cake
libs
tests/cases/libs
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
?>
|
Loading…
Add table
Reference in a new issue