diff --git a/src/Collection/CollectionTrait.php b/src/Collection/CollectionTrait.php index 739bcaba8b9..40d498f6b92 100644 --- a/src/Collection/CollectionTrait.php +++ b/src/Collection/CollectionTrait.php @@ -22,6 +22,7 @@ use Cake\Collection\Iterator\MapReduce; use Cake\Collection\Iterator\ReplaceIterator; use Cake\Collection\Iterator\SortIterator; +use Cake\Collection\Iterator\SyncIterator; use LimitIterator; /** @@ -750,6 +751,28 @@ public function nest($idPath, $parentPath) { return new Collection($collection); } + public function insert($path, $values) { + $iterator = new SyncIterator($this, new Collection($values)); + $collection = new Collection($iterator); + $path = explode('.', $path); + $target = array_pop($path); + + return $collection->map(function($values) use ($path, $target) { + list($row, $insert) = $values; + $pointer =& $row; + + foreach ($path as $step) { + if (!isset($pointer[$step])) { + return $row; + } + $pointer =& $pointer[$step]; + } + + $pointer[$target] = $insert; + return $row; + }); + } + /** * Returns an array representation of the results * diff --git a/src/Collection/Iterator/SyncIterator.php b/src/Collection/Iterator/SyncIterator.php new file mode 100644 index 00000000000..d8976fce0de --- /dev/null +++ b/src/Collection/Iterator/SyncIterator.php @@ -0,0 +1,34 @@ +attachIterator($left); + $this->attachIterator($right); + } + + public function key() { + $key = parent::key(); + return $key[0]; + } + +} diff --git a/src/ORM/Association.php b/src/ORM/Association.php index bf51cb7544b..447d921ad3c 100644 --- a/src/ORM/Association.php +++ b/src/ORM/Association.php @@ -491,6 +491,30 @@ protected function _copyAttributes($query, $surrogate, $options) { if (!empty($options['fields'])) { $query->select($query->aliasFields($options['fields'], $target->alias())); } + + foreach ($surrogate->formatResults() as $callable) { + $query->formatResults(function($results) use ($callable) { + $property = $this->property(); + $extracted = $callable($results->extract($property))->compile(); + return $results->insert($property, $extracted); + }); + } + + $this->_bindNewAssociations($query, $surrogate, $options); + } + + protected function _bindNewAssociations($query, $surrogate, $options) { + $contain = $surrogate->contain(); + $target = $this->_targetTable; + if ($contain) { + $loader = $surrogate->eagerLoader(); + $loader->attachAssociations($query, $target, $options['includeFields']); + $newBinds = []; + foreach ($contain as $alias => $value) { + $newBinds[$options['path'] . '.' . $alias] = $value; + } + $query->contain($newBinds); + } } /** diff --git a/src/ORM/EagerLoader.php b/src/ORM/EagerLoader.php index 42c9738c6d9..91fb707246d 100644 --- a/src/ORM/EagerLoader.php +++ b/src/ORM/EagerLoader.php @@ -251,7 +251,10 @@ public function attachAssociations(Query $query, Table $repository, $includeFiel } foreach ($this->attachableAssociations($repository) as $options) { - $config = $options['config'] + ['includeFields' => $includeFields]; + $config = $options['config'] + [ + 'path' => $options['path'], + 'includeFields' => $includeFields + ]; $options['instance']->attachTo($query, $config); } } diff --git a/tests/Fixture/TranslateFixture.php b/tests/Fixture/TranslateFixture.php index bd84d2840de..8191441f217 100644 --- a/tests/Fixture/TranslateFixture.php +++ b/tests/Fixture/TranslateFixture.php @@ -75,5 +75,6 @@ class TranslateFixture extends TestFixture { array('locale' => 'eng', 'model' => 'Comments', 'foreign_key' => 3, 'field' => 'comment', 'content' => 'Comment #3'), array('locale' => 'eng', 'model' => 'Comments', 'foreign_key' => 4, 'field' => 'comment', 'content' => 'Comment #4'), array('locale' => 'spa', 'model' => 'Comments', 'foreign_key' => 4, 'field' => 'comment', 'content' => 'Comentario #4'), + array('locale' => 'eng', 'model' => 'Authors', 'foreign_key' => 1, 'field' => 'name', 'content' => 'May-rianoh') ); } diff --git a/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php b/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php index 092fca5ecfc..22ff697f57c 100644 --- a/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php +++ b/tests/TestCase/Model/Behavior/TranslateBehaviorTest.php @@ -410,4 +410,50 @@ public function testTranslationsHasManyWithOverride() { $this->assertEquals('Obsah #1', $results->first()->body); } +/** + * Tests that it is possible to translate belongsTo associations + * + * @return void + */ + public function testFindSingleLocaleBelongsto() { + $table = TableRegistry::get('Articles'); + $table->addBehavior('Translate', ['fields' => ['title', 'body']]); + $authors = $table->belongsTo('Authors')->target(); + $authors->addBehavior('Translate', ['fields' => ['name']]); + + $table->locale('eng'); + $authors->locale('eng'); + + $results = $table->find() + ->select(['title', 'body']) + ->contain(['Authors' => function($q) { + return $q->select(['id', 'name']); + }]); + + $expected = [ + [ + 'title' => 'Title #1', + 'body' => 'Content #1', + 'author' => ['id' => 1, 'name' => 'May-rianoh', '_locale' => 'eng'], + '_locale' => 'eng' + ], + [ + 'title' => 'Title #2', + 'body' => 'Content #2', + 'author' => ['id' => 3, 'name' => 'larry', '_locale' => 'eng'], + '_locale' => 'eng' + ], + [ + 'title' => 'Title #3', + 'body' => 'Content #3', + 'author' => ['id' => 1, 'name' => 'May-rianoh', '_locale' => 'eng'], + '_locale' => 'eng' + ] + ]; + $results = array_map(function($r) { + return $r->toArray(); + }, $results->toArray()); + $this->assertEquals($expected, $results); + } + }