From 8db3d690ab1b7399b112757816833f4239e0a78b Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Sun, 2 Feb 2014 12:16:06 +0100 Subject: [PATCH] Working towards supporting contain() on beforeFind for attachable associations --- src/ORM/Association.php | 21 +-- .../ORM/Association/BelongsToManyTest.php | 126 ++++-------------- 2 files changed, 39 insertions(+), 108 deletions(-) diff --git a/src/ORM/Association.php b/src/ORM/Association.php index c91590fb3c9..14017c07886 100644 --- a/src/ORM/Association.php +++ b/src/ORM/Association.php @@ -410,14 +410,14 @@ public function attachTo(Query $query, array $options = []) { $options['conditions'] = $query->newExpr()->add($options['conditions']); $extraOptions = []; + $dummy = $target->query(); if (!empty($options['queryBuilder'])) { - $newQuery = $options['queryBuilder']($target->query()); - $options['fields'] = $newQuery->clause('select') ?: $options['fields']; - $options['conditions']->add($newQuery->clause('where') ?: []); - $extraOptions = $newQuery->getOptions(); + $dummy = $options['queryBuilder']($dummy); } + $this->_dispatchBeforeFind($dummy); + $options = $this->_copyAttributes($dummy, $options); $joinOptions = ['table' => 1, 'conditions' => 1, 'type' => 1]; $query->join([$target->alias() => array_intersect_key($options, $joinOptions)]); @@ -431,8 +431,6 @@ public function attachTo(Query $query, array $options = []) { if (!empty($options['fields'])) { $query->select($query->aliasFields($options['fields'], $target->alias())); } - - $this->_dispatchBeforeFind($query, $extraOptions); } /** @@ -482,15 +480,22 @@ public function find($type = 'all', $options = []) { * attaching to * * @param \Cake\ORM\Query $query the query this association is attaching itself to - * @param array $options extra options to passed to the association * @return void */ - protected function _dispatchBeforeFind($query, $options) { + protected function _dispatchBeforeFind($query) { $table = $this->target(); + $options = $query->getOptions(); $event = new Event('Model.beforeFind', $table, [$query, $options, false]); $table->getEventManager()->dispatch($event); } + protected function _copyAttributes($query, $options) { + debug($query->contain()); + $options['fields'] = $query->clause('select') ?: $options['fields']; + $options['conditions']->add($query->clause('where') ?: []); + return $options; + } + /** * Returns a single or multiple condition(s) to be appended to the generated join * clause for getting the results on the target table. If false is returned then diff --git a/tests/TestCase/ORM/Association/BelongsToManyTest.php b/tests/TestCase/ORM/Association/BelongsToManyTest.php index cbbb1e91b3c..7d6d47acda0 100644 --- a/tests/TestCase/ORM/Association/BelongsToManyTest.php +++ b/tests/TestCase/ORM/Association/BelongsToManyTest.php @@ -60,6 +60,16 @@ public function setUp() { ] ]); TableRegistry::set('Articles', $this->article); + TableRegistry::get('ArticlesTags', [ + 'table' => 'articles_tags', + 'schema' => [ + 'article_id' => ['type' => 'integer'], + 'tag_id' => ['type' => 'integer'], + '_constraints' => [ + 'primary' => ['type' => 'primary', 'columns' => ['article_id', 'tag_id']] + ] + ] + ]); } /** @@ -210,16 +220,6 @@ public function testAttachTo() { 'targetTable' => $this->tag, 'conditions' => ['Tags.name' => 'cake'] ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['article_id', 'tag_id']] - ] - ] - ]); $association = new BelongsToMany('Tags', $config); $query->expects($this->at(0))->method('join')->with([ 'Tags' => [ @@ -267,13 +267,6 @@ public function testAttachToNoFields() { 'targetTable' => $this->tag, 'conditions' => ['Tags.name' => 'cake'] ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'] - ] - ]); $association = new BelongsToMany('Tags', $config); $query->expects($this->at(0))->method('join')->with([ 'Tags' => [ @@ -315,13 +308,6 @@ public function testAttachToWithQueryBuilder() { 'targetTable' => $this->tag, 'conditions' => ['Tags.name' => 'cake'] ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'] - ] - ]); $association = new BelongsToMany('Tags', $config); $query->expects($this->at(0))->method('join')->with([ 'Tags' => [ @@ -419,13 +405,6 @@ public function testEagerLoader() { 'sourceTable' => $this->article, 'targetTable' => $this->tag, ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'] - ] - ]); $association = new BelongsToMany('Tags', $config); $keys = [1, 2, 3, 4]; $query = $this->getMock('Cake\ORM\Query', ['all', 'matching'], [null, null]); @@ -486,13 +465,6 @@ public function testEagerLoaderWithDefaults() { 'conditions' => ['Tags.name' => 'foo'], 'sort' => ['id' => 'ASC'], ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'] - ] - ]); $association = new BelongsToMany('Tags', $config); $keys = [1, 2, 3, 4]; $methods = ['all', 'matching', 'where', 'order']; @@ -550,13 +522,6 @@ public function testEagerLoaderWithOverrides() { 'conditions' => ['Tags.name' => 'foo'], 'sort' => ['id' => 'ASC'], ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'] - ] - ]); $association = new BelongsToMany('Tags', $config); $keys = [1, 2, 3, 4]; $methods = ['all', 'matching', 'where', 'order', 'select']; @@ -627,13 +592,6 @@ public function testEagerLoaderFieldsException() { 'conditions' => ['Tags.name' => 'foo'], 'sort' => ['id' => 'ASC'], ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'] - ] - ]); $association = new BelongsToMany('Tags', $config); $keys = [1, 2, 3, 4]; $methods = ['all', 'contain', 'where', 'order', 'select']; @@ -665,16 +623,6 @@ public function testEagerLoaderSubquery() { 'conditions' => ['Tags.name' => 'foo'], 'sort' => ['id' => 'ASC'], ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'], - '_constraints' => [ - 'PK' => ['type' => 'primary', 'columns' => ['article_id', 'tag_id']] - ] - ] - ]); $association = new BelongsToMany('Tags', $config); $parent = (new Query(null, $this->article)) ->join(['foo' => ['table' => 'foo', 'type' => 'inner', 'conditions' => []]]) @@ -760,13 +708,6 @@ public function testEagerLoaderWithQueryBuilder() { 'sourceTable' => $this->article, 'targetTable' => $this->tag, ]; - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'] - ] - ]); $association = new BelongsToMany('Tags', $config); $keys = [1, 2, 3, 4]; $query = $this->getMock( @@ -833,13 +774,12 @@ public function testEagerLoaderMultipleKeys() { ]; $this->article->primaryKey(['id', 'site_id']); $this->tag->primaryKey(['id', 'site_id']); - TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'], - 'site_id' => ['type' => 'integer'], - ] + + $table= TableRegistry::get('ArticlesTags'); + $table->schema([ + 'article_id' => ['type' => 'integer'], + 'tag_id' => ['type' => 'integer'], + 'site_id' => ['type' => 'integer'], ]); $association = new BelongsToMany('Tags', $config); $keys = [[1, 10], [2, 20], [3, 30], [4, 40]]; @@ -1535,26 +1475,19 @@ public function testAttachToBeforeFind() { 'sourceTable' => $this->article, 'targetTable' => $this->tag, ]; - $table = TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['article_id', 'tag_id']] - ] - ] - ]); + $table = TableRegistry::get('ArticlesTags'); $association = new BelongsToMany('Tags', $config); $listener = $this->getMock('stdClass', ['__invoke']); $this->tag->getEventManager()->attach($listener, 'Model.beforeFind'); + $newQuery = $this->tag->query(); $listener->expects($this->once())->method('__invoke') - ->with($this->isInstanceOf('\Cake\Event\Event'), $query, [], false); + ->with($this->isInstanceOf('\Cake\Event\Event'), $newQuery, [], false); $listener2 = $this->getMock('stdClass', ['__invoke']); $table->getEventManager()->attach($listener2, 'Model.beforeFind'); + $newQuery2 = $table->query(); $listener2->expects($this->once())->method('__invoke') - ->with($this->isInstanceOf('\Cake\Event\Event'), $query, [], false); + ->with($this->isInstanceOf('\Cake\Event\Event'), $newQuery2, [], false); $association->attachTo($query); } @@ -1571,27 +1504,20 @@ public function testAttachToBeforeFindExtraOptions() { 'sourceTable' => $this->article, 'targetTable' => $this->tag, ]; - $table = TableRegistry::get('ArticlesTags', [ - 'table' => 'articles_tags', - 'schema' => [ - 'article_id' => ['type' => 'integer'], - 'tag_id' => ['type' => 'integer'], - '_constraints' => [ - 'primary' => ['type' => 'primary', 'columns' => ['article_id', 'tag_id']] - ] - ] - ]); + $table = TableRegistry::get('ArticlesTags'); $association = new BelongsToMany('Tags', $config); $listener = $this->getMock('stdClass', ['__invoke']); $this->tag->getEventManager()->attach($listener, 'Model.beforeFind'); $opts = ['somthing' => 'more']; + $newQuery = $this->tag->query()->applyOptions($opts); $listener->expects($this->once())->method('__invoke') - ->with($this->isInstanceOf('\Cake\Event\Event'), $query, $opts, false); + ->with($this->isInstanceOf('\Cake\Event\Event'), $newQuery, $opts, false); $listener2 = $this->getMock('stdClass', ['__invoke']); $table->getEventManager()->attach($listener2, 'Model.beforeFind'); + $newQuery2 = $table->query(); $listener2->expects($this->once())->method('__invoke') - ->with($this->isInstanceOf('\Cake\Event\Event'), $query, [], false); + ->with($this->isInstanceOf('\Cake\Event\Event'), $newQuery2, [], false); $association->attachTo($query, ['queryBuilder' => function($q) { return $q->applyOptions(['somthing' => 'more']);