diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 40fdafb940..8cca25b02d 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -180,6 +180,7 @@ Yii Framework 2 Change Log - Enh #9072: `yii\web\ErrorAction` displays 404 error instead of blank page on direct access (klimov-paul) - Enh #9149: Print directory migrationPath in a `yii migrate` command error. (RusAlex) - Enh #9177: Added password hash cost setting to Security component (freezy-sk) +- Enh #9198: Added parameter visibleButtons for `yii\grid\ActionColimn` (fornit1917) - Enh #9239: Better handling of `Json` errors (grzegorzkurtyka, samdark) - Enh #9246: Added `yii\web\UrlRule::getParamRules()` (df2) - Enh #9249: Added `hashCallback` in `yii\web\AssetManager` to allow custom hash generation for asset directory (petrabarus) diff --git a/framework/grid/ActionColumn.php b/framework/grid/ActionColumn.php index d7353d1314..3c2119e60e 100644 --- a/framework/grid/ActionColumn.php +++ b/framework/grid/ActionColumn.php @@ -85,6 +85,28 @@ class ActionColumn extends Column * ``` */ public $buttons = []; + /** @var array visibility conditions for each button. The array keys are the button names (without curly brackets), + * and the values are are the boolean true/false or the anonymous function. The button will be shown, + * when its name is not specified in this array. + * The callbacks must use the following signature: + * + * ```php + * [ + * 'update' => function ($model, $key, $index) { + * return $model->status === 'editable'; + * }, + * ], + * ``` + * + * Or you can pass a boolean expression: + * + * ```php + * [ + * 'update' => \Yii::$app->user->can('update'), + * ], + * ``` + */ + public $visibleButtons = []; /** * @var callable a callback that creates a button URL using the specified model information. * The signature of the callback should be the same as that of [[createUrl()]]. @@ -174,9 +196,17 @@ class ActionColumn extends Column { return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) { $name = $matches[1]; - if (isset($this->buttons[$name])) { - $url = $this->createUrl($name, $model, $key, $index); + if (isset($this->visibleButtons[$name])) { + $isVisible = $this->visibleButtons[$name] instanceof \Closure + ? call_user_func($this->visibleButtons[$name], $model, $key, $index) + : $this->visibleButtons[$name]; + } else { + $isVisible = true; + } + + if ($isVisible && isset($this->buttons[$name])) { + $url = $this->createUrl($name, $model, $key, $index); return call_user_func($this->buttons[$name], $url, $model, $key); } else { return ''; diff --git a/tests/framework/grid/ActionColumnTest.php b/tests/framework/grid/ActionColumnTest.php new file mode 100644 index 0000000000..a4243062a6 --- /dev/null +++ b/tests/framework/grid/ActionColumnTest.php @@ -0,0 +1,63 @@ + + * + * @group grid + */ +class ActionColumnTest extends \yiiunit\TestCase +{ + public function testRenderDataCell() + { + $column = new ActionColumn(); + $column->urlCreator = function($model, $key, $index) { + return 'http://test.com'; + }; + $column->template = '{update}'; + $column->buttons = [ + 'update' => function($url, $model, $key) { + return 'update_button'; + } + ]; + + //test default visible button + $columnContents = $column->renderDataCell(['id' => 1], 1, 0); + $this->assertContains('update_button', $columnContents); + + //test visible button + $column->visibleButtons = [ + 'update' => true + ]; + $columnContents = $column->renderDataCell(['id' => 1], 1, 0); + $this->assertContains('update_button', $columnContents); + + //test visible button (condition is callback) + $column->visibleButtons = [ + 'update' => function($model, $key, $index){return $model['id'] == 1;} + ]; + $columnContents = $column->renderDataCell(['id' => 1], 1, 0); + $this->assertContains('update_button', $columnContents); + + //test invisible button + $column->visibleButtons = [ + 'update' => false + ]; + $columnContents = $column->renderDataCell(['id' => 1], 1, 0); + $this->assertNotContains('update_button', $columnContents); + + //test invisible button (condition is callback) + $column->visibleButtons = [ + 'update' => function($model, $key, $index){return $model['id'] != 1;} + ]; + $columnContents = $column->renderDataCell(['id' => 1], 1, 0); + $this->assertNotContains('update_button', $columnContents); + + } +} \ No newline at end of file