left join support in TranslateBehavior

This commit is contained in:
Val Bancer 2017-06-12 21:41:35 +02:00
parent 910d04584f
commit 0bfb19f126
3 changed files with 78 additions and 18 deletions

View file

@ -60,6 +60,25 @@ class TranslateBehavior extends ModelBehavior {
* $config could be empty - and translations configured dynamically by * $config could be empty - and translations configured dynamically by
* bindTranslation() method * bindTranslation() method
* *
* By default INNER joins are used to fetch translations. In order to use
* other join types $config should contain 'join_type' key:
* ```
* array(
* 'fields' => array('field_one', 'field_two' => 'FieldAssoc', 'field_three'),
* 'join_type' => 'LEFT',
* )
* ```
* In a model it may be configured this way:
* ```
* public $actsAs = array(
* 'Translate' => array(
* 'content',
* 'title',
* 'join_type' => 'LEFT',
* ),
* );
* ```
*
* @param Model $Model Model the behavior is being attached to. * @param Model $Model Model the behavior is being attached to.
* @param array $config Array of configuration information. * @param array $config Array of configuration information.
* @return mixed * @return mixed
@ -74,9 +93,16 @@ class TranslateBehavior extends ModelBehavior {
return false; return false;
} }
$this->settings[$Model->alias] = array(); $this->settings[$Model->alias] = array(
'fields' => array(),
'join_type' => 'INNER',
);
$this->runtime[$Model->alias] = array('fields' => array()); $this->runtime[$Model->alias] = array('fields' => array());
$this->translateModel($Model); $this->translateModel($Model);
if (isset($config['join_type'])) {
$this->settings[$Model->alias]['join_type'] = $config['join_type'];
unset($config['join_type']);
}
return $this->bindTranslation($Model, $config, false); return $this->bindTranslation($Model, $config, false);
} }
@ -124,7 +150,7 @@ class TranslateBehavior extends ModelBehavior {
if (is_string($query['fields']) && $query['fields'] === "COUNT(*) AS {$db->name('count')}") { if (is_string($query['fields']) && $query['fields'] === "COUNT(*) AS {$db->name('count')}") {
$query['fields'] = "COUNT(DISTINCT({$db->name($Model->escapeField())})) {$db->alias}count"; $query['fields'] = "COUNT(DISTINCT({$db->name($Model->escapeField())})) {$db->alias}count";
$query['joins'][] = array( $query['joins'][] = array(
'type' => 'INNER', 'type' => $this->settings[$Model->alias]['join_type'],
'alias' => $RuntimeModel->alias, 'alias' => $RuntimeModel->alias,
'table' => $joinTable, 'table' => $joinTable,
'conditions' => array( 'conditions' => array(
@ -144,7 +170,7 @@ class TranslateBehavior extends ModelBehavior {
} }
$fields = array_merge( $fields = array_merge(
$this->settings[$Model->alias], $this->settings[$Model->alias]['fields'],
$this->runtime[$Model->alias]['fields'] $this->runtime[$Model->alias]['fields']
); );
$addFields = array(); $addFields = array();
@ -200,7 +226,7 @@ class TranslateBehavior extends ModelBehavior {
return $conditionFields; return $conditionFields;
} }
foreach ($query['conditions'] as $col => $val) { foreach ($query['conditions'] as $col => $val) {
foreach ($this->settings[$Model->alias] as $field => $assoc) { foreach ($this->settings[$Model->alias]['fields'] as $field => $assoc) {
if (is_numeric($field)) { if (is_numeric($field)) {
$field = $assoc; $field = $assoc;
} }
@ -254,7 +280,7 @@ class TranslateBehavior extends ModelBehavior {
$query['fields'][] = $aliasVirtual; $query['fields'][] = $aliasVirtual;
} }
$query['joins'][] = array( $query['joins'][] = array(
'type' => 'INNER', 'type' => $this->settings[$Model->alias]['join_type'],
'alias' => $alias, 'alias' => $alias,
'table' => $joinTable, 'table' => $joinTable,
'conditions' => array( 'conditions' => array(
@ -374,7 +400,7 @@ class TranslateBehavior extends ModelBehavior {
if (empty($locale)) { if (empty($locale)) {
return true; return true;
} }
$fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']); $fields = array_merge($this->settings[$Model->alias]['fields'], $this->runtime[$Model->alias]['fields']);
$tempData = array(); $tempData = array();
foreach ($fields as $key => $value) { foreach ($fields as $key => $value) {
@ -488,7 +514,7 @@ class TranslateBehavior extends ModelBehavior {
* @return array The fully populated data to save. * @return array The fully populated data to save.
*/ */
protected function _prepareTranslations(Model $Model, $data) { protected function _prepareTranslations(Model $Model, $data) {
$fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']); $fields = array_merge($this->settings[$Model->alias]['fields'], $this->runtime[$Model->alias]['fields']);
$locales = array(); $locales = array();
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
if (is_array($value)) { if (is_array($value)) {
@ -612,14 +638,14 @@ class TranslateBehavior extends ModelBehavior {
if ($reset) { if ($reset) {
$this->runtime[$Model->alias]['fields'][] = $field; $this->runtime[$Model->alias]['fields'][] = $field;
} else { } else {
$this->settings[$Model->alias][] = $field; $this->settings[$Model->alias]['fields'][] = $field;
} }
} else { } else {
if ($reset) { if ($reset) {
$this->runtime[$Model->alias]['fields'][$field] = $association; $this->runtime[$Model->alias]['fields'][$field] = $association;
$this->runtime[$Model->alias]['restoreFields'][] = $field; $this->runtime[$Model->alias]['restoreFields'][] = $field;
} else { } else {
$this->settings[$Model->alias][$field] = $association; $this->settings[$Model->alias]['fields'][$field] = $association;
} }
foreach (array('hasOne', 'hasMany', 'belongsTo', 'hasAndBelongsToMany') as $type) { foreach (array('hasOne', 'hasMany', 'belongsTo', 'hasAndBelongsToMany') as $type) {
@ -652,10 +678,10 @@ class TranslateBehavior extends ModelBehavior {
* @return void * @return void
*/ */
protected function _removeField(Model $Model, $field) { protected function _removeField(Model $Model, $field) {
if (array_key_exists($field, $this->settings[$Model->alias])) { if (array_key_exists($field, $this->settings[$Model->alias]['fields'])) {
unset($this->settings[$Model->alias][$field]); unset($this->settings[$Model->alias]['fields'][$field]);
} elseif (in_array($field, $this->settings[$Model->alias])) { } elseif (in_array($field, $this->settings[$Model->alias]['fields'])) {
$this->settings[$Model->alias] = array_merge(array_diff($this->settings[$Model->alias], array($field))); $this->settings[$Model->alias]['fields'] = array_merge(array_diff($this->settings[$Model->alias]['fields'], array($field)));
} }
if (array_key_exists($field, $this->runtime[$Model->alias]['fields'])) { if (array_key_exists($field, $this->runtime[$Model->alias]['fields'])) {
@ -675,11 +701,11 @@ class TranslateBehavior extends ModelBehavior {
* @return bool * @return bool
*/ */
public function unbindTranslation(Model $Model, $fields = null) { public function unbindTranslation(Model $Model, $fields = null) {
if (empty($fields) && empty($this->settings[$Model->alias])) { if (empty($fields) && empty($this->settings[$Model->alias]['fields'])) {
return false; return false;
} }
if (empty($fields)) { if (empty($fields)) {
return $this->unbindTranslation($Model, $this->settings[$Model->alias]); return $this->unbindTranslation($Model, $this->settings[$Model->alias]['fields']);
} }
if (is_string($fields)) { if (is_string($fields)) {

View file

@ -528,6 +528,29 @@ class TranslateBehaviorTest extends CakeTestCase {
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
} }
public function testMissingTranslationLeftJoin() {
$this->loadFixtures('Translate', 'TranslatedItem');
$expected = array(
'TranslatedItem' => Array (
'id' => '1',
'translated_article_id' => '1',
'slug' => 'first_translated',
'locale' => 'rus',
'content' => '',
'title' => '',
),
);
$TestModel = new TranslatedItemLeftJoin();
$TestModel->locale = 'rus';
$result = $TestModel->read(null, 1);
$this->assertEquals($expected, $result);
$TestModel->locale = array('rus');
$result = $TestModel->read(null, 1);
$this->assertEquals($expected, $result);
}
/** /**
* testTranslatedFindList method * testTranslatedFindList method
* *
@ -1376,15 +1399,15 @@ class TranslateBehaviorTest extends CakeTestCase {
$Model->unbindTranslation(); $Model->unbindTranslation();
$Model->bindTranslation(array('body', 'slug'), false); $Model->bindTranslation(array('body', 'slug'), false);
$result = $Model->Behaviors->Translate->settings['TranslatedItem']; $result = $Model->Behaviors->Translate->settings['TranslatedItem']['fields'];
$this->assertEquals(array('body', 'slug'), $result); $this->assertEquals(array('body', 'slug'), $result);
$Model->unbindTranslation(array('body')); $Model->unbindTranslation(array('body'));
$result = $Model->Behaviors->Translate->settings['TranslatedItem']; $result = $Model->Behaviors->Translate->settings['TranslatedItem']['fields'];
$this->assertNotContains('body', $result); $this->assertNotContains('body', $result);
$Model->unbindTranslation('slug'); $Model->unbindTranslation('slug');
$result = $Model->Behaviors->Translate->settings['TranslatedItem']; $result = $Model->Behaviors->Translate->settings['TranslatedItem']['fields'];
$this->assertNotContains('slug', $result); $this->assertNotContains('slug', $result);
} }

View file

@ -3247,6 +3247,17 @@ class TranslatedItem extends CakeTestModel {
} }
class TranslatedItemLeftJoin extends TranslatedItem {
public $actsAs = array(
'Translate' => array(
'content',
'title',
'join_type' => 'LEFT',
)
);
}
/** /**
* TranslatedItem class. * TranslatedItem class.
* *