diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index fef773f5b2..7f6157697e 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -9,6 +9,7 @@ Yii Framework 2 Change Log - Enh #17345: Improved performance of `yii\db\Connection::quoteColumnName()` (brandonkelly) - Enh #17348: Improved performance of `yii\db\Connection::quoteTableName()` (brandonkelly) - Enh #17353: Added `sameSite` support for `yii\web\Cookie` and `yii\web\Session::cookieParams` (rhertogh) +- Bug #17341: Allow callable objects to be set to `\yii\filters\AccessRule::$roleParams` (alexkart) 2.0.20 June 04, 2019 diff --git a/framework/filters/AccessRule.php b/framework/filters/AccessRule.php index a6966c27ae..5a52fa8ad0 100644 --- a/framework/filters/AccessRule.php +++ b/framework/filters/AccessRule.php @@ -240,7 +240,7 @@ class AccessRule extends Component } } else { if (!isset($roleParams)) { - $roleParams = $this->roleParams instanceof Closure ? call_user_func($this->roleParams, $this) : $this->roleParams; + $roleParams = !is_array($this->roleParams) && is_callable($this->roleParams) ? call_user_func($this->roleParams, $this) : $this->roleParams; } if ($user->can($item, $roleParams)) { return true; diff --git a/tests/framework/filters/AccessRuleTest.php b/tests/framework/filters/AccessRuleTest.php index 199faa3d9a..c30cf5de05 100644 --- a/tests/framework/filters/AccessRuleTest.php +++ b/tests/framework/filters/AccessRuleTest.php @@ -363,6 +363,30 @@ class AccessRuleTest extends \yiiunit\TestCase $this->assertTrue($rule->allows($action, $user, $request)); } + /** + * Test that callable object can be used as roleParams values + */ + public function testMatchRoleWithRoleParamsCallable() + { + $action = $this->mockAction(); + $action->id = 'update'; + + $auth = $this->mockAuthManager(); + $request = $this->mockRequest(); + + $rule = new AccessRule([ + 'allow' => true, + 'roles' => ['updatePost'], + 'actions' => ['update'], + 'roleParams' => new RoleParamCallableObject(), + ]); + + $user = $this->mockUser('user2'); + $user->accessChecker = $auth; + + $this->assertEquals(true, $rule->allows($action, $user, $request)); + } + public function testMatchVerb() { $action = $this->mockAction(); @@ -566,3 +590,11 @@ class AccessRuleTest extends \yiiunit\TestCase $this->assertNull($rule->allows($action, $user, $request)); } } + +class RoleParamCallableObject +{ + public function __invoke() + { + return ['authorID' => 'user2']; + } +}