Skip to content

Commit

Permalink
Merge branch '2.0' into 2.1
Browse files Browse the repository at this point in the history
Conflicts:
	lib/Cake/Model/BehaviorCollection.php
	lib/Cake/basics.php
  • Loading branch information
markstory committed Jan 9, 2012
2 parents c029316 + f4c27e0 commit 0e56d74
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 104 deletions.
2 changes: 1 addition & 1 deletion lib/Cake/Controller/Component/PaginatorComponent.php
Expand Up @@ -333,7 +333,7 @@ public function validateSort($object, $options, $whitelist = array()) {
$options['order'] = array($options['sort'] => $direction);
}

if (!empty($whitelist)) {
if (!empty($whitelist) && isset($options['order']) && is_array($options['order'])) {
$field = key($options['order']);
if (!in_array($field, $whitelist)) {
$options['order'] = null;
Expand Down
2 changes: 1 addition & 1 deletion lib/Cake/Core/Configure.php
Expand Up @@ -312,7 +312,7 @@ public static function load($key, $config = 'default', $merge = true) {
$keys = array_keys($values);
foreach ($keys as $key) {
if (($c = self::read($key)) && is_array($values[$key]) && is_array($c)) {
$values[$key] = array_merge_recursive($c, $values[$key]);
$values[$key] = Set::merge($c, $values[$key]);
}
}
}
Expand Down
143 changes: 107 additions & 36 deletions lib/Cake/Model/Behavior/TranslateBehavior.php
Expand Up @@ -34,6 +34,20 @@ class TranslateBehavior extends ModelBehavior {
*/
public $runtime = array();

/**
* Stores the joinTable object for generating joins.
*
* @var object
*/
var $_joinTable;

/**
* Stores the runtime model for generating joins.
*
* @var Model
*/
var $_runtimeModel;

/**
* Callback
*
Expand Down Expand Up @@ -94,6 +108,7 @@ public function beforeFind($model, $query) {
}
$db = $model->getDataSource();
$RuntimeModel = $this->translateModel($model);

if (!empty($RuntimeModel->tablePrefix)) {
$tablePrefix = $RuntimeModel->tablePrefix;
} else {
Expand All @@ -104,8 +119,11 @@ public function beforeFind($model, $query) {
$joinTable->table = $RuntimeModel->table;
$joinTable->schemaName = $RuntimeModel->getDataSource()->getSchemaName();

$this->_joinTable = $joinTable;
$this->_runtimeModel = $RuntimeModel;

if (is_string($query['fields']) && 'COUNT(*) AS ' . $db->name('count') == $query['fields']) {
$query['fields'] = 'COUNT(DISTINCT(' . $db->name($model->alias . '.' . $model->primaryKey) . ')) ' . $db->alias . 'count';
$query['fields'] = 'COUNT(DISTINCT('.$db->name($model->alias . '.' . $model->primaryKey) . ')) ' . $db->alias . 'count';
$query['joins'][] = array(
'type' => 'INNER',
'alias' => $RuntimeModel->alias,
Expand All @@ -116,6 +134,11 @@ public function beforeFind($model, $query) {
$RuntimeModel->alias.'.locale' => $locale
)
);
$conditionFields = $this->_checkConditions($model, $query);
foreach ($conditionFields as $field) {
$query = $this->_addJoin($model, $query, $field, $field, $locale);
}
unset($this->_joinTable, $this->_runtimeModel);
return $query;
}

Expand Down Expand Up @@ -145,45 +168,93 @@ public function beforeFind($model, $query) {
unset($query['fields'][$key]);
}
}
$query = $this->_addJoin($model, $query, $field, $aliasField, $locale);
}
}
$this->runtime[$model->alias]['beforeFind'] = $addFields;
unset($this->_joinTable, $this->_runtimeModel);
return $query;
}

if (is_array($locale)) {
foreach ($locale as $_locale) {
$model->virtualFields['i18n_' . $field . '_' . $_locale] = 'I18n__' . $field . '__' . $_locale . '.content';
if (!empty($query['fields'])) {
$query['fields'][] = 'i18n_' . $field . '_' . $_locale;
}
$query['joins'][] = array(
'type' => 'LEFT',
'alias' => 'I18n__' . $field . '__' . $_locale,
'table' => $joinTable,
'conditions' => array(
$model->alias . '.' . $model->primaryKey => $db->identifier("I18n__{$field}__{$_locale}.foreign_key"),
'I18n__' . $field . '__' . $_locale . '.model' => $model->name,
'I18n__' . $field . '__' . $_locale . '.' . $RuntimeModel->displayField => $aliasField,
'I18n__' . $field . '__' . $_locale . '.locale' => $_locale
)
);
}
} else {
$model->virtualFields['i18n_' . $field] = 'I18n__' . $field . '.content';
if (!empty($query['fields'])) {
$query['fields'][] = 'i18n_' . $field;
}
$query['joins'][] = array(
'type' => 'INNER',
'alias' => 'I18n__' . $field,
'table' => $joinTable,
'conditions' => array(
$model->alias . '.' . $model->primaryKey => $db->identifier("I18n__{$field}.foreign_key"),
'I18n__' . $field . '.model' => $model->name,
'I18n__' . $field . '.' . $RuntimeModel->displayField => $aliasField,
'I18n__' . $field . '.locale' => $locale
)
);
/**
* Check a query's conditions for translated fields.
* Return an array of translated fields found in the conditions.
*
* @param Model $model The model being read.
* @param array $query The query array.
* @return array The list of translated fields that are in the conditions.
*/
protected function _checkConditions(Model $model, $query) {
$conditionFields = array();
if (empty($query['conditions']) || (!empty($query['conditions']) && !is_array($query['conditions'])) ) {
return $conditionFields;
}
foreach ($query['conditions'] as $col => $val) {
foreach ($this->settings[$model->alias] as $field => $assoc) {
if (is_numeric($field)) {
$field = $assoc;
}
if (strpos($col, $field) !== false) {
$conditionFields[] = $field;
}
}
}
$this->runtime[$model->alias]['beforeFind'] = $addFields;
return $conditionFields;
}

/**
* Appends a join for translated fields and possibly a field.
*
* @param Model $model The model being worked on.
* @param object $joinTable The jointable object.
* @param array $query The query array to append a join to.
* @param string $field The field name being joined.
* @param string $aliasField The aliased field name being joined.
* @param mixed $locale The locale(s) having joins added.
* @param boolean $addField Whether or not to add a field.
* @return array The modfied query
*/
protected function _addJoin(Model $model, $query, $field, $aliasField, $locale, $addField = false) {
$db = ConnectionManager::getDataSource($model->useDbConfig);

$RuntimeModel = $this->_runtimeModel;
$joinTable = $this->_joinTable;

if (is_array($locale)) {
foreach ($locale as $_locale) {
$model->virtualFields['i18n_' . $field . '_' . $_locale] = 'I18n__' . $field . '__' . $_locale . '.content';
if (!empty($query['fields']) && is_array($query['fields'])) {
$query['fields'][] = 'i18n_'.$field.'_'.$_locale;
}
$query['joins'][] = array(
'type' => 'LEFT',
'alias' => 'I18n__'.$field.'__'.$_locale,
'table' => $joinTable,
'conditions' => array(
$model->alias . '.' . $model->primaryKey => $db->identifier("I18n__{$field}__{$_locale}.foreign_key"),
'I18n__'.$field.'__'.$_locale.'.model' => $model->name,
'I18n__'.$field.'__'.$_locale.'.'.$RuntimeModel->displayField => $aliasField,
'I18n__'.$field.'__'.$_locale.'.locale' => $_locale
)
);
}
} else {
$model->virtualFields['i18n_' . $field] = 'I18n__' . $field . '.content';
if (!empty($query['fields']) && is_array($query['fields'])) {
$query['fields'][] = 'i18n_'.$field;
}
$query['joins'][] = array(
'type' => 'INNER',
'alias' => 'I18n__'.$field,
'table' => $joinTable,
'conditions' => array(
$model->alias . '.' . $model->primaryKey => $db->identifier("I18n__{$field}.foreign_key"),
'I18n__'.$field.'.model' => $model->name,
'I18n__'.$field.'.'.$RuntimeModel->displayField => $aliasField,
'I18n__'.$field.'.locale' => $locale
)
);
}
return $query;
}

Expand Down
6 changes: 4 additions & 2 deletions lib/Cake/Model/BehaviorCollection.php
Expand Up @@ -107,6 +107,9 @@ public function load($behavior, $config = array()) {
$alias = $behavior;
$behavior = $config['className'];
}
$configDisabled = isset($config['enabled']) && $config['enabled'] === false;
unset($config['enabled'], $config['className']);

list($plugin, $name) = pluginSplit($behavior, true);
if (!isset($alias)) {
$alias = $name;
Expand Down Expand Up @@ -166,8 +169,7 @@ public function load($behavior, $config = array()) {
}
}

$enable = isset($config['enabled']) ? $config['enabled'] : true;
if ($enable) {
if (!in_array($alias, $this->_enabled) && !$configDisabled) {
$this->enable($alias);
} else {
$this->disable($alias);
Expand Down
16 changes: 3 additions & 13 deletions lib/Cake/Model/Datasource/Database/Sqlserver.php
Expand Up @@ -182,7 +182,7 @@ public function listSources($data = null) {
} else {
$tables = array();

while ($line = $result->fetch()) {
while ($line = $result->fetch(PDO::FETCH_NUM)) {
$tables[] = $line[0];
}

Expand Down Expand Up @@ -222,7 +222,7 @@ public function describe($model) {
throw new CakeException(__d('cake_dev', 'Could not describe table for %s', $table));
}

foreach ($cols as $column) {
while ($column = $cols->fetch(PDO::FETCH_OBJ)) {
$field = $column->Field;
$fields[$field] = array(
'type' => $this->column($column),
Expand Down Expand Up @@ -645,14 +645,7 @@ public function insertMulti($table, $fields, $values) {
$this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' ON');
}

$table = $this->fullTableName($table);
$fields = implode(', ', array_map(array(&$this, 'name'), $fields));
$this->begin();
foreach ($values as $value) {
$holder = implode(', ', array_map(array(&$this, 'value'), $value));
$this->_execute("INSERT INTO {$table} ({$fields}) VALUES ({$holder})");
}
$this->commit();
parent::insertMulti($table, $fields, $values);

if ($hasPrimaryKey) {
$this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' OFF');
Expand Down Expand Up @@ -717,9 +710,6 @@ public function buildIndex($indexes, $table = null) {
* @return string
*/
protected function _getPrimaryKey($model) {
if (!is_object($model)) {
$model = new Model(false, $model);
}
$schema = $this->describe($model);
foreach ($schema as $field => $props) {
if (isset($props['key']) && $props['key'] == 'primary') {
Expand Down
20 changes: 20 additions & 0 deletions lib/Cake/Test/Case/Controller/Component/PaginatorComponentTest.php
Expand Up @@ -776,6 +776,26 @@ public function testValidateSortMultiple() {
$this->assertEquals($expected, $result['order']);
}

/**
* Test that no sort doesn't trigger an error.
*
* @return void
*/
public function testValidateSortNoSort() {
$model = $this->getMock('Model');
$model->alias = 'model';
$model->expects($this->any())->method('hasField')->will($this->returnValue(true));

$options = array('direction' => 'asc');
$result = $this->Paginator->validateSort($model, $options, array('title', 'id'));
$this->assertFalse(isset($result['order']));

$options = array('order' => 'invalid desc');
$result = $this->Paginator->validateSort($model, $options, array('title', 'id'));

$this->assertEquals($options['order'], $result['order']);
}

/**
* test that maxLimit is respected
*
Expand Down
2 changes: 2 additions & 0 deletions lib/Cake/Test/Case/Core/ConfigureTest.php
Expand Up @@ -224,6 +224,8 @@ public function testLoadWithMerge() {
$this->assertEquals('value2', Configure::read('Read'));
$this->assertEquals('buried2', Configure::read('Deep.Second.SecondDeepest'));
$this->assertEquals('buried', Configure::read('Deep.Deeper.Deepest'));
$this->assertEquals('Overwrite', Configure::read('TestAcl.classname'));
$this->assertEquals('one', Configure::read('TestAcl.custom'));
}

/**
Expand Down
18 changes: 18 additions & 0 deletions lib/Cake/Test/Case/Model/Behavior/TranslateBehaviorTest.php
Expand Up @@ -58,6 +58,24 @@ public function tearDown() {
ClassRegistry::flush();
}

/**
* Test that count queries with conditions get the correct joins
*
* @return void
*/
function testCountWithConditions() {
$this->loadFixtures('Translate', 'TranslatedItem');

$Model =& new TranslatedItem();
$Model->locale = 'eng';
$result = $Model->find('count', array(
'conditions' => array(
'I18n__content.locale' => 'eng'
)
));
$this->assertEqual(3, $result);
}

/**
* testTranslateModel method
*
Expand Down
15 changes: 14 additions & 1 deletion lib/Cake/Test/Case/Model/BehaviorCollectionTest.php
Expand Up @@ -419,9 +419,22 @@ class BehaviorCollectionTest extends CakeTestCase {
*/
public $fixtures = array(
'core.apple', 'core.sample', 'core.article', 'core.user', 'core.comment',
'core.attachment', 'core.tag', 'core.articles_tag'
'core.attachment', 'core.tag', 'core.articles_tag', 'core.translate'
);

/**
* Test load() with enabled => false
*
*/
public function testLoadDisabled() {
$Apple = new Apple();
$this->assertSame($Apple->Behaviors->attached(), array());

$Apple->Behaviors->load('Translate', array('enabled' => false));
$this->assertTrue($Apple->Behaviors->attached('Translate'));
$this->assertFalse($Apple->Behaviors->enabled('Translate'));
}

/**
* Tests loading aliased behaviors
*/
Expand Down

0 comments on commit 0e56d74

Please sign in to comment.