Browse Source

Merge pull request #9518 from saeideng/type

Apply TypeMap into matching/notMatching/innerJoinWith

This change allows complex types to be correctly handled in where()
for joined associations.
Mark Story 9 years ago
parent
commit
5b0204ccb0
2 changed files with 151 additions and 4 deletions
  1. 8 4
      src/ORM/Query.php
  2. 143 0
      tests/TestCase/ORM/QueryRegressionTest.php

+ 8 - 4
src/ORM/Query.php

@@ -450,7 +450,8 @@ class Query extends DatabaseQuery implements JsonSerializable, QueryInterface
      */
     public function matching($assoc, callable $builder = null)
     {
-        $this->eagerLoader()->matching($assoc, $builder);
+        $result = $this->eagerLoader()->matching($assoc, $builder);
+        $this->_addAssociationsToTypeMap($this->repository(), $this->typeMap(), $result);
         $this->_dirty();
 
         return $this;
@@ -521,10 +522,11 @@ class Query extends DatabaseQuery implements JsonSerializable, QueryInterface
      */
     public function leftJoinWith($assoc, callable $builder = null)
     {
-        $this->eagerLoader()->matching($assoc, $builder, [
+        $result = $this->eagerLoader()->matching($assoc, $builder, [
             'joinType' => 'LEFT',
             'fields' => false
         ]);
+        $this->_addAssociationsToTypeMap($this->repository(), $this->typeMap(), $result);
         $this->_dirty();
 
         return $this;
@@ -567,10 +569,11 @@ class Query extends DatabaseQuery implements JsonSerializable, QueryInterface
      */
     public function innerJoinWith($assoc, callable $builder = null)
     {
-        $this->eagerLoader()->matching($assoc, $builder, [
+        $result = $this->eagerLoader()->matching($assoc, $builder, [
             'joinType' => 'INNER',
             'fields' => false
         ]);
+        $this->_addAssociationsToTypeMap($this->repository(), $this->typeMap(), $result);
         $this->_dirty();
 
         return $this;
@@ -628,11 +631,12 @@ class Query extends DatabaseQuery implements JsonSerializable, QueryInterface
      */
     public function notMatching($assoc, callable $builder = null)
     {
-        $this->eagerLoader()->matching($assoc, $builder, [
+        $result = $this->eagerLoader()->matching($assoc, $builder, [
             'joinType' => 'LEFT',
             'fields' => false,
             'negateMatch' => true
         ]);
+        $this->_addAssociationsToTypeMap($this->repository(), $this->typeMap(), $result);
         $this->_dirty();
 
         return $this;

+ 143 - 0
tests/TestCase/ORM/QueryRegressionTest.php

@@ -1209,6 +1209,149 @@ class QueryRegressionTest extends TestCase
     }
 
     /**
+     * Test that matching queries map types correctly.
+     *
+     * @return void
+     */
+    public function testComplexTypesInJoinedWhereWithMatching()
+    {
+        $this->loadFixtures('Comments', 'Users', 'Articles');
+        $table = TableRegistry::get('Users');
+        $table->hasOne('Comments', [
+            'foreignKey' => 'user_id',
+        ]);
+        $table->Comments->belongsTo('Articles');
+        $table->Comments->Articles->belongsTo('Authors', [
+            'className' => 'Users',
+            'foreignKey' => 'author_id'
+        ]);
+
+        $query = $table->find()
+            ->matching('Comments')
+            ->where([
+                'Comments.updated >' => new \DateTime('2007-03-18 10:55:00')
+            ]);
+
+        $result = $query->first();
+        $this->assertNotEmpty($result);
+        $this->assertInstanceOf('Cake\I18n\Time', $result->_matchingData['Comments']->updated);
+
+
+        $query = $table->find()
+            ->matching('Comments.Articles.Authors')
+            ->where([
+                'Authors.created >' => new \DateTime('2007-03-17 01:16:00')
+            ]);
+
+        $result = $query->first();
+        $this->assertNotEmpty($result);
+        $this->assertInstanceOf('Cake\I18n\Time', $result->_matchingData['Authors']->updated);
+    }
+
+    /**
+     * Test that notMatching queries map types correctly.
+     *
+     * @return void
+     */
+    public function testComplexTypesInJoinedWhereWithNotMatching()
+    {
+        $this->loadFixtures('Articles', 'Tags', 'ArticlesTags');
+        $Tags = TableRegistry::get('Tags');
+        $Tags->belongsToMany('Articles');
+
+        $query = $Tags->find()
+            ->notMatching('Articles', function ($q) {
+                return $q ->where(['ArticlesTags.tag_id !=' => 3 ]);
+            })
+            ->where([
+                'Tags.created <' => new \DateTime('2016-01-02 00:00:00')
+            ]);
+
+        $result = $query->first();
+        $this->assertNotEmpty($result);
+        $this->assertEquals(3, $result->id);
+        $this->assertInstanceOf('Cake\I18n\Time', $result->created);
+    }
+
+    /**
+     * Test that innerJoinWith queries map types correctly.
+     *
+     * @return void
+     */
+    public function testComplexTypesInJoinedWhereWithInnerJoinWith()
+    {
+        $this->loadFixtures('Comments', 'Users', 'Articles');
+        $table = TableRegistry::get('Users');
+        $table->hasOne('Comments', [
+            'foreignKey' => 'user_id',
+        ]);
+        $table->Comments->belongsTo('Articles');
+        $table->Comments->Articles->belongsTo('Authors', [
+            'className' => 'Users',
+            'foreignKey' => 'author_id'
+        ]);
+
+        $query = $table->find()
+            ->innerJoinWith('Comments')
+            ->where([
+                'Comments.updated >' => new \DateTime('2007-03-18 10:55:00')
+            ]);
+
+        $result = $query->first();
+        $this->assertNotEmpty($result);
+        $this->assertInstanceOf('Cake\I18n\Time', $result->updated);
+
+        $query = $table->find()
+            ->innerJoinWith('Comments.Articles.Authors')
+            ->where([
+                'Authors.created >' => new \DateTime('2007-03-17 01:16:00')
+            ]);
+
+        $result = $query->first();
+        $this->assertNotEmpty($result);
+        $this->assertInstanceOf('Cake\I18n\Time', $result->updated);
+    }
+
+    /**
+     * Test that leftJoinWith queries map types correctly.
+     *
+     * @return void
+     */
+    public function testComplexTypesInJoinedWhereWithLeftJoinWith()
+    {
+        $this->loadFixtures('Comments', 'Users', 'Articles');
+        $table = TableRegistry::get('Users');
+        $table->hasOne('Comments', [
+            'foreignKey' => 'user_id',
+        ]);
+        $table->Comments->belongsTo('Articles');
+        $table->Comments->Articles->belongsTo('Authors', [
+            'className' => 'Users',
+            'foreignKey' => 'author_id'
+        ]);
+
+        $query = $table->find()
+            ->leftJoinWith('Comments')
+            ->where([
+                'Comments.updated >' => new \DateTime('2007-03-18 10:55:00')
+            ]);
+
+        $result = $query->first();
+        $this->assertNotEmpty($result);
+        $this->assertInstanceOf('Cake\I18n\Time', $result->updated);
+
+        $query = $table->find()
+            ->leftJoinWith('Comments.Articles.Authors')
+            ->where([
+                'Authors.created >' => new \DateTime('2007-03-17 01:16:00')
+            ]);
+
+        $result = $query->first();
+        $this->assertNotEmpty($result);
+        $this->assertInstanceOf('Cake\I18n\Time', $result->updated);
+    }
+
+    /**
      * Tests that it is possible to contain to fetch
      * associations off of a junction table.
      *