Completed
Push — static-messages ( 2be6d4...bb00c2 )
by Alexander
82:26 queued 45:33
created

ActionColumn::initDefaultButton()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 27
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 27
rs 8.439
cc 6
eloc 22
nc 2
nop 3
1
<?php
2
/**
3
 * @link http://www.yiiframework.com/
4
 * @copyright Copyright (c) 2008 Yii Software LLC
5
 * @license http://www.yiiframework.com/license/
6
 */
7
8
namespace yii\grid;
9
10
use Yii;
11
use yii\helpers\Html;
12
use yii\helpers\Url;
13
14
/**
15
 * ActionColumn is a column for the [[GridView]] widget that displays buttons for viewing and manipulating the items.
16
 *
17
 * To add an ActionColumn to the gridview, add it to the [[GridView::columns|columns]] configuration as follows:
18
 *
19
 * ```php
20
 * 'columns' => [
21
 *     // ...
22
 *     [
23
 *         'class' => ActionColumn::className(),
24
 *         // you may configure additional properties here
25
 *     ],
26
 * ]
27
 * ```
28
 *
29
 * For more details and usage information on ActionColumn, see the [guide article on data widgets](guide:output-data-widgets).
30
 *
31
 * @author Qiang Xue <[email protected]>
32
 * @since 2.0
33
 */
34
class ActionColumn extends Column
35
{
36
    /**
37
     * @inheritdoc
38
     */
39
    public $headerOptions = ['class' => 'action-column'];
40
    /**
41
     * @var string the ID of the controller that should handle the actions specified here.
42
     * If not set, it will use the currently active controller. This property is mainly used by
43
     * [[urlCreator]] to create URLs for different actions. The value of this property will be prefixed
44
     * to each action name to form the route of the action.
45
     */
46
    public $controller;
47
    /**
48
     * @var string the template used for composing each cell in the action column.
49
     * Tokens enclosed within curly brackets are treated as controller action IDs (also called *button names*
50
     * in the context of action column). They will be replaced by the corresponding button rendering callbacks
51
     * specified in [[buttons]]. For example, the token `{view}` will be replaced by the result of
52
     * the callback `buttons['view']`. If a callback cannot be found, the token will be replaced with an empty string.
53
     *
54
     * As an example, to only have the view, and update button you can add the ActionColumn to your GridView columns as follows:
55
     *
56
     * ```php
57
     * ['class' => 'yii\grid\ActionColumn', 'template' => '{view} {update}'],
58
     * ```
59
     *
60
     * @see buttons
61
     */
62
    public $template = '{view} {update} {delete}';
63
    /**
64
     * @var array button rendering callbacks. The array keys are the button names (without curly brackets),
65
     * and the values are the corresponding button rendering callbacks. The callbacks should use the following
66
     * signature:
67
     *
68
     * ```php
69
     * function ($url, $model, $key) {
70
     *     // return the button HTML code
71
     * }
72
     * ```
73
     *
74
     * where `$url` is the URL that the column creates for the button, `$model` is the model object
75
     * being rendered for the current row, and `$key` is the key of the model in the data provider array.
76
     *
77
     * You can add further conditions to the button, for example only display it, when the model is
78
     * editable (here assuming you have a status field that indicates that):
79
     *
80
     * ```php
81
     * [
82
     *     'update' => function ($url, $model, $key) {
83
     *         return $model->status === 'editable' ? Html::a('Update', $url) : '';
84
     *     },
85
     * ],
86
     * ```
87
     */
88
    public $buttons = [];
89
    /** @var array visibility conditions for each button. The array keys are the button names (without curly brackets),
90
     * and the values are the boolean true/false or the anonymous function. When the button name is not specified in
91
     * this array it will be shown by default.
92
     * The callbacks must use the following signature:
93
     *
94
     * ```php
95
     * function ($model, $key, $index) {
96
     *     return $model->status === 'editable';
97
     * }
98
     * ```
99
     *
100
     * Or you can pass a boolean value:
101
     *
102
     * ```php
103
     * [
104
     *     'update' => \Yii::$app->user->can('update'),
105
     * ],
106
     * ```
107
     * @since 2.0.7
108
     */
109
    public $visibleButtons = [];
110
    /**
111
     * @var callable a callback that creates a button URL using the specified model information.
112
     * The signature of the callback should be the same as that of [[createUrl()]]
113
     * Since 2.0.10 it can accept additional parameter, which refers to the column instance itself:
114
     *
115
     * ```php
116
     * function (string $action, mixed $model, mixed $key, integer $index, ActionColumn $this) {
117
     *     //return string;
118
     * }
119
     * ```
120
     *
121
     * If this property is not set, button URLs will be created using [[createUrl()]].
122
     */
123
    public $urlCreator;
124
    /**
125
     * @var array html options to be applied to the [[initDefaultButton()|default button]].
126
     * @since 2.0.4
127
     */
128
    public $buttonOptions = [];
129
130
131
    /**
132
     * @inheritdoc
133
     */
134
    public function init()
135
    {
136
        parent::init();
137
        $this->initDefaultButtons();
138
    }
139
140
    /**
141
     * Initializes the default button rendering callbacks.
142
     */
143
    protected function initDefaultButtons()
144
    {
145
        $this->initDefaultButton('view', 'eye-open');
146
        $this->initDefaultButton('update', 'pencil');
147
        $this->initDefaultButton('delete', 'trash', [
148
            'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
149
            'data-method' => 'post',
150
        ]);
151
    }
152
153
    /**
154
     * Initializes the default button rendering callback for single button
155
     * @param string $name Button name as it's written in template
156
     * @param string $iconName The part of Bootstrap glyphicon class that makes it unique
157
     * @param array $additionalOptions Array of additional options
158
     * @since 2.0.11
159
     */
160
    protected function initDefaultButton($name, $iconName, $additionalOptions = [])
161
    {
162
        if (!isset($this->buttons[$name]) && strpos($this->template, '{' . $name . '}') !== false) {
163
            $this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions) {
0 ignored issues
show
Unused Code introduced by
The parameter $model is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
164
                switch ($name) {
165
                    case 'view':
166
                        $title = Yii::t('yii', 'View');
167
                        break;
168
                    case 'update':
169
                        $title = Yii::t('yii', 'Update');
170
                        break;
171
                    case 'delete':
172
                        $title = Yii::t('yii', 'Delete');
173
                        break;
174
                    default:
175
                        $title = ucfirst($name);
176
                }
177
                $options = array_merge([
178
                    'title' => $title,
179
                    'aria-label' => $title,
180
                    'data-pjax' => '0',
181
                ], $additionalOptions, $this->buttonOptions);
182
                $icon = Html::tag('span', '', ['class' => "glyphicon glyphicon-$iconName"]);
183
                return Html::a($icon, $url, $options);
184
            };
185
        }
186
    }
187
188
    /**
189
     * Creates a URL for the given action and model.
190
     * This method is called for each button and each row.
191
     * @param string $action the button name (or action ID)
192
     * @param \yii\db\ActiveRecord $model the data model
193
     * @param mixed $key the key associated with the data model
194
     * @param int $index the current row index
195
     * @return string the created URL
196
     */
197
    public function createUrl($action, $model, $key, $index)
198
    {
199
        if (is_callable($this->urlCreator)) {
200
            return call_user_func($this->urlCreator, $action, $model, $key, $index, $this);
201
        } else {
202
            $params = is_array($key) ? $key : ['id' => (string) $key];
203
            $params[0] = $this->controller ? $this->controller . '/' . $action : $action;
204
205
            return Url::toRoute($params);
206
        }
207
    }
208
209
    /**
210
     * @inheritdoc
211
     */
212
    protected function renderDataCellContent($model, $key, $index)
213
    {
214
        return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) {
215
            $name = $matches[1];
216
217
            if (isset($this->visibleButtons[$name])) {
218
                $isVisible = $this->visibleButtons[$name] instanceof \Closure
219
                    ? call_user_func($this->visibleButtons[$name], $model, $key, $index)
220
                    : $this->visibleButtons[$name];
221
            } else {
222
                $isVisible = true;
223
            }
224
225
            if ($isVisible && isset($this->buttons[$name])) {
226
                $url = $this->createUrl($name, $model, $key, $index);
227
                return call_user_func($this->buttons[$name], $url, $model, $key);
228
            } else {
229
                return '';
230
            }
231
        }, $this->template);
232
    }
233
}
234