ソースを参照

Merge pull request #6023 from patrickconroy/3.0-strategy-lockdown

3.0 - Strategy lockdown
José Lorenzo Rodríguez 11 年 前
コミット
9a92534875

+ 8 - 2
src/ORM/Association.php

@@ -173,6 +173,13 @@ abstract class Association
     protected $_finder = 'all';
 
     /**
+     * Valid strategies for this association. Subclasses can narrow this down.
+     *
+     * @var array
+     */
+    protected $_validStrategies = [self::STRATEGY_JOIN, self::STRATEGY_SELECT, self::STRATEGY_SUBQUERY];
+
+    /**
      * Constructor. Subclasses can override _options function to get the original
      * list of passed options if expecting any other special key
      *
@@ -401,8 +408,7 @@ abstract class Association
     public function strategy($name = null)
     {
         if ($name !== null) {
-            $valid = [self::STRATEGY_JOIN, self::STRATEGY_SELECT, self::STRATEGY_SUBQUERY];
-            if (!in_array($name, $valid)) {
+            if (!in_array($name, $this->_validStrategies)) {
                 throw new \InvalidArgumentException(
                     sprintf('Invalid strategy "%s" was provided', $name)
                 );

+ 7 - 0
src/ORM/Association/BelongsTo.php

@@ -33,6 +33,13 @@ class BelongsTo extends Association
     use SelectableAssociationTrait;
 
     /**
+     * Valid strategies for this type of association
+     *
+     * @var array
+     */
+    protected $_validStrategies = [self::STRATEGY_JOIN, self::STRATEGY_SELECT];
+
+    /**
      * Sets the name of the field representing the foreign key to the target table.
      * If no parameters are passed current field is returned
      *

+ 8 - 1
src/ORM/Association/BelongsToMany.php

@@ -61,7 +61,7 @@ class BelongsToMany extends Association
      *
      * @var string
      */
-    protected $_strategy = parent::STRATEGY_SELECT;
+    protected $_strategy = self::STRATEGY_SELECT;
 
     /**
      * Junction table instance
@@ -115,6 +115,13 @@ class BelongsToMany extends Association
     protected $_through;
 
     /**
+     * Valid strategies for this type of association
+     *
+     * @var array
+     */
+    protected $_validStrategies = [self::STRATEGY_SELECT, self::STRATEGY_SUBQUERY];
+
+    /**
      * Sets the name of the field representing the foreign key to the target table.
      * If no parameters are passed current field is returned
      *

+ 8 - 1
src/ORM/Association/HasMany.php

@@ -45,7 +45,14 @@ class HasMany extends Association
      *
      * @var string
      */
-    protected $_strategy = parent::STRATEGY_SELECT;
+    protected $_strategy = self::STRATEGY_SELECT;
+
+    /**
+     * Valid strategies for this type of association
+     *
+     * @var array
+     */
+    protected $_validStrategies = [self::STRATEGY_SELECT, self::STRATEGY_SUBQUERY];
 
     /**
      * Returns whether or not the passed table is the owning side for this

+ 7 - 0
src/ORM/Association/HasOne.php

@@ -34,6 +34,13 @@ class HasOne extends Association
     use SelectableAssociationTrait;
 
     /**
+     * Valid strategies for this type of association
+     *
+     * @var array
+     */
+    protected $_validStrategies = [self::STRATEGY_JOIN, self::STRATEGY_SELECT];
+
+    /**
      * Sets the name of the field representing the foreign key to the target table.
      * If no parameters are passed current field is returned
      *

+ 13 - 0
tests/TestCase/ORM/Association/BelongsToManyTest.php

@@ -141,6 +141,19 @@ class BelongsToManyTest extends TestCase
     }
 
     /**
+     * Tests that BelongsToMany can't use the join strategy
+     *
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Invalid strategy "join" was provided
+     * @return void
+     */
+    public function testStrategyFailure()
+    {
+        $assoc = new BelongsToMany('Test');
+        $assoc->strategy(BelongsToMany::STRATEGY_JOIN);
+    }
+
+    /**
      * Tests the junction method
      *
      * @return void

+ 13 - 0
tests/TestCase/ORM/Association/HasManyTest.php

@@ -123,6 +123,19 @@ class HasManyTest extends TestCase
     }
 
     /**
+     * Tests that HasMany can't use the join strategy
+     *
+     * @expectedException \InvalidArgumentException
+     * @expectedExceptionMessage Invalid strategy "join" was provided
+     * @return void
+     */
+    public function testStrategyFailure()
+    {
+        $assoc = new HasMany('Test');
+        $assoc->strategy(HasMany::STRATEGY_JOIN);
+    }
+
+    /**
      * Test the eager loader method with no extra options
      *
      * @return void

+ 35 - 15
tests/TestCase/ORM/CompositeKeysTest.php

@@ -63,11 +63,41 @@ class CompositeKeyTest extends TestCase
     }
 
     /**
+     * Data provider for the two types of strategies HasOne implements
+     *
+     * @return void
+     */
+    public function strategiesProviderHasOne()
+    {
+        return [['join'], ['select']];
+    }
+
+    /**
      * Data provider for the two types of strategies HasMany implements
      *
      * @return void
      */
-    public function strategiesProvider()
+    public function strategiesProviderHasMany()
+    {
+        return [['subquery'], ['select']];
+    }
+
+    /**
+     * Data provider for the two types of strategies BelongsTo implements
+     *
+     * @return void
+     */
+    public function strategiesProviderBelongsTo()
+    {
+        return [['join'], ['select']];
+    }
+
+    /**
+     * Data provider for the two types of strategies BelongsToMany implements
+     *
+     * @return void
+     */
+    public function strategiesProviderBelongsToMany()
     {
         return [['subquery'], ['select']];
     }
@@ -76,7 +106,7 @@ class CompositeKeyTest extends TestCase
      * Tests that HasMany associations are correctly eager loaded and results
      * correctly nested when multiple foreignKeys are used
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderHasMany
      * @return void
      */
     public function testHasManyEager($strategy)
@@ -152,7 +182,7 @@ class CompositeKeyTest extends TestCase
      * Tests that BelongsToMany associations are correctly eager loaded when multiple
      * foreignKeys are used
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderBelongsToMany
      * @return void
      */
     public function testBelongsToManyEager($strategy)
@@ -237,19 +267,9 @@ class CompositeKeyTest extends TestCase
     }
 
     /**
-     * Provides strategies for associations that can be joined
-     *
-     * @return void
-     */
-    public function internalStategiesProvider()
-    {
-        return [['join'], ['select'], ['subquery']];
-    }
-
-    /**
      * Tests loding belongsTo with composite keys
      *
-     * @dataProvider internalStategiesProvider
+     * @dataProvider strategiesProviderBelongsTo
      * @return void
      */
     public function testBelongsToEager($strategy)
@@ -298,7 +318,7 @@ class CompositeKeyTest extends TestCase
     /**
      * Tests loding hasOne with composite keys
      *
-     * @dataProvider internalStategiesProvider
+     * @dataProvider strategiesProviderHasOne
      * @return void
      */
     public function testHasOneEager($strategy)

+ 33 - 23
tests/TestCase/ORM/QueryTest.php

@@ -103,20 +103,40 @@ class QueryTest extends TestCase
     }
 
     /**
-     * Provides strategies for associations that can be joined
+     * Data provider for the two types of strategies HasMany implements
+     *
+     * @return void
+     */
+    public function strategiesProviderHasMany()
+    {
+        return [['subquery'], ['select']];
+    }
+
+    /**
+     * Data provider for the two types of strategies BelongsTo implements
+     *
+     * @return void
+     */
+    public function strategiesProviderBelongsTo()
+    {
+        return [['join'], ['select']];
+    }
+
+    /**
+     * Data provider for the two types of strategies BelongsToMany implements
      *
      * @return void
      */
-    public function internalStategiesProvider()
+    public function strategiesProviderBelongsToMany()
     {
-        return [['join'], ['select'], ['subquery']];
+        return [['subquery'], ['select']];
     }
 
     /**
      * Tests that results are grouped correctly when using contain()
      * and results are not hydrated
      *
-     * @dataProvider internalStategiesProvider
+     * @dataProvider strategiesProviderBelongsTo
      * @return void
      */
     public function testContainResultFetchingOneLevel($strategy)
@@ -169,22 +189,12 @@ class QueryTest extends TestCase
     }
 
     /**
-     * Data provider for the two types of strategies HasMany implements
-     *
-     * @return void
-     */
-    public function strategiesProvider()
-    {
-        return [['subquery'], ['select']];
-    }
-
-    /**
      * Tests that HasMany associations are correctly eager loaded and results
      * correctly nested when no hydration is used
      * Also that the query object passes the correct parent model keys to the
      * association objects in order to perform eager loading with select strategy
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderHasMany
      * @return void
      */
     public function testHasManyEagerLoadingNoHydration($strategy)
@@ -263,7 +273,7 @@ class QueryTest extends TestCase
      * Tests that it is possible to count results containing hasMany associations
      * both hydrating and not hydrating the results.
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderHasMany
      * @return void
      */
     public function testHasManyEagerLoadingCount($strategy)
@@ -294,7 +304,7 @@ class QueryTest extends TestCase
     /**
      * Tests that it is possible to set fields & order in a hasMany result set
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderHasMany
      * @return void
      */
     public function testHasManyEagerLoadingFieldsAndOrderNoHydration($strategy)
@@ -346,7 +356,7 @@ class QueryTest extends TestCase
     /**
      * Tests that deep associations can be eagerly loaded
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderHasMany
      * @return void
      */
     public function testHasManyEagerLoadingDeep($strategy)
@@ -420,7 +430,7 @@ class QueryTest extends TestCase
      * Tests that hasMany associations can be loaded even when related to a secondary
      * model in the query
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderHasMany
      * @return void
      */
     public function testHasManyEagerLoadingFromSecondaryTable($strategy)
@@ -526,7 +536,7 @@ class QueryTest extends TestCase
      * Also that the query object passes the correct parent model keys to the
      * association objects in order to perform eager loading with select strategy
      *
-     * @dataProvider strategiesProvider
+     * @dataProvider strategiesProviderBelongsToMany
      * @return void
      */
     public function testBelongsToManyEagerLoadingNoHydration($strategy)
@@ -1278,7 +1288,7 @@ class QueryTest extends TestCase
     /**
      * Tests that belongsTo relations are correctly hydrated
      *
-     * @dataProvider internalStategiesProvider
+     * @dataProvider strategiesProviderBelongsTo
      * @return void
      */
     public function testHydrateBelongsTo($strategy)
@@ -1303,7 +1313,7 @@ class QueryTest extends TestCase
     /**
      * Tests that deeply nested associations are also hydrated correctly
      *
-     * @dataProvider internalStategiesProvider
+     * @dataProvider strategiesProviderBelongsTo
      * @return void
      */
     public function testHydrateDeep($strategy)
@@ -2201,7 +2211,7 @@ class QueryTest extends TestCase
      * Tests that it is possible to use the same association aliases in the association
      * chain for contain
      *
-     * @dataProvider internalStategiesProvider
+     * @dataProvider strategiesProviderBelongsTo
      * @return void
      */
     public function testRepeatedAssociationAliases($strategy)