ActionColumn.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. namespace yii\grid;
  8. use Yii;
  9. use yii\helpers\Html;
  10. use yii\helpers\Url;
  11. /**
  12. * ActionColumn is a column for the [[GridView]] widget that displays buttons for viewing and manipulating the items.
  13. *
  14. * To add an ActionColumn to the gridview, add it to the [[GridView::columns|columns]] configuration as follows:
  15. *
  16. * ```php
  17. * 'columns' => [
  18. * // ...
  19. * [
  20. * 'class' => ActionColumn::className(),
  21. * // you may configure additional properties here
  22. * ],
  23. * ]
  24. * ```
  25. *
  26. * For more details and usage information on ActionColumn, see the [guide article on data widgets](guide:output-data-widgets).
  27. *
  28. * @author Qiang Xue <qiang.xue@gmail.com>
  29. * @since 2.0
  30. */
  31. class ActionColumn extends Column
  32. {
  33. /**
  34. * {@inheritdoc}
  35. */
  36. public $headerOptions = ['class' => 'action-column'];
  37. /**
  38. * @var string the ID of the controller that should handle the actions specified here.
  39. * If not set, it will use the currently active controller. This property is mainly used by
  40. * [[urlCreator]] to create URLs for different actions. The value of this property will be prefixed
  41. * to each action name to form the route of the action.
  42. */
  43. public $controller;
  44. /**
  45. * @var string the template used for composing each cell in the action column.
  46. * Tokens enclosed within curly brackets are treated as controller action IDs (also called *button names*
  47. * in the context of action column). They will be replaced by the corresponding button rendering callbacks
  48. * specified in [[buttons]]. For example, the token `{view}` will be replaced by the result of
  49. * the callback `buttons['view']`. If a callback cannot be found, the token will be replaced with an empty string.
  50. *
  51. * As an example, to only have the view, and update button you can add the ActionColumn to your GridView columns as follows:
  52. *
  53. * ```php
  54. * ['class' => 'yii\grid\ActionColumn', 'template' => '{view} {update}'],
  55. * ```
  56. *
  57. * @see buttons
  58. */
  59. public $template = '{view} {update} {delete}';
  60. /**
  61. * @var array button rendering callbacks. The array keys are the button names (without curly brackets),
  62. * and the values are the corresponding button rendering callbacks. The callbacks should use the following
  63. * signature:
  64. *
  65. * ```php
  66. * function ($url, $model, $key) {
  67. * // return the button HTML code
  68. * }
  69. * ```
  70. *
  71. * where `$url` is the URL that the column creates for the button, `$model` is the model object
  72. * being rendered for the current row, and `$key` is the key of the model in the data provider array.
  73. *
  74. * You can add further conditions to the button, for example only display it, when the model is
  75. * editable (here assuming you have a status field that indicates that):
  76. *
  77. * ```php
  78. * [
  79. * 'update' => function ($url, $model, $key) {
  80. * return $model->status === 'editable' ? Html::a('Update', $url) : '';
  81. * },
  82. * ],
  83. * ```
  84. */
  85. public $buttons = [];
  86. /** @var array visibility conditions for each button. The array keys are the button names (without curly brackets),
  87. * and the values are the boolean true/false or the anonymous function. When the button name is not specified in
  88. * this array it will be shown by default.
  89. * The callbacks must use the following signature:
  90. *
  91. * ```php
  92. * function ($model, $key, $index) {
  93. * return $model->status === 'editable';
  94. * }
  95. * ```
  96. *
  97. * Or you can pass a boolean value:
  98. *
  99. * ```php
  100. * [
  101. * 'update' => \Yii::$app->user->can('update'),
  102. * ],
  103. * ```
  104. * @since 2.0.7
  105. */
  106. public $visibleButtons = [];
  107. /**
  108. * @var callable a callback that creates a button URL using the specified model information.
  109. * The signature of the callback should be the same as that of [[createUrl()]]
  110. * Since 2.0.10 it can accept additional parameter, which refers to the column instance itself:
  111. *
  112. * ```php
  113. * function (string $action, mixed $model, mixed $key, integer $index, ActionColumn $this) {
  114. * //return string;
  115. * }
  116. * ```
  117. *
  118. * If this property is not set, button URLs will be created using [[createUrl()]].
  119. */
  120. public $urlCreator;
  121. /**
  122. * @var array html options to be applied to the [[initDefaultButton()|default button]].
  123. * @since 2.0.4
  124. */
  125. public $buttonOptions = [];
  126. /**
  127. * {@inheritdoc}
  128. */
  129. public function init()
  130. {
  131. parent::init();
  132. $this->initDefaultButtons();
  133. }
  134. /**
  135. * Initializes the default button rendering callbacks.
  136. */
  137. protected function initDefaultButtons()
  138. {
  139. $this->initDefaultButton('view', 'eye-open');
  140. $this->initDefaultButton('update', 'pencil');
  141. $this->initDefaultButton('delete', 'trash', [
  142. 'data-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?'),
  143. 'data-method' => 'post',
  144. ]);
  145. }
  146. /**
  147. * Initializes the default button rendering callback for single button.
  148. * @param string $name Button name as it's written in template
  149. * @param string $iconName The part of Bootstrap glyphicon class that makes it unique
  150. * @param array $additionalOptions Array of additional options
  151. * @since 2.0.11
  152. */
  153. protected function initDefaultButton($name, $iconName, $additionalOptions = [])
  154. {
  155. if (!isset($this->buttons[$name]) && strpos($this->template, '{' . $name . '}') !== false) {
  156. $this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions) {
  157. switch ($name) {
  158. case 'view':
  159. $title = Yii::t('yii', 'View');
  160. break;
  161. case 'update':
  162. $title = Yii::t('yii', 'Update');
  163. break;
  164. case 'delete':
  165. $title = Yii::t('yii', 'Delete');
  166. break;
  167. default:
  168. $title = ucfirst($name);
  169. }
  170. $options = array_merge([
  171. 'title' => $title,
  172. 'aria-label' => $title,
  173. 'data-pjax' => '0',
  174. ], $additionalOptions, $this->buttonOptions);
  175. $icon = Html::tag('span', '', ['class' => "glyphicon glyphicon-$iconName"]);
  176. return Html::a($icon, $url, $options);
  177. };
  178. }
  179. }
  180. /**
  181. * Creates a URL for the given action and model.
  182. * This method is called for each button and each row.
  183. * @param string $action the button name (or action ID)
  184. * @param \yii\db\ActiveRecordInterface $model the data model
  185. * @param mixed $key the key associated with the data model
  186. * @param int $index the current row index
  187. * @return string the created URL
  188. */
  189. public function createUrl($action, $model, $key, $index)
  190. {
  191. if (is_callable($this->urlCreator)) {
  192. return call_user_func($this->urlCreator, $action, $model, $key, $index, $this);
  193. }
  194. $params = is_array($key) ? $key : ['id' => (string) $key];
  195. $params[0] = $this->controller ? $this->controller . '/' . $action : $action;
  196. return Url::toRoute($params);
  197. }
  198. /**
  199. * {@inheritdoc}
  200. */
  201. protected function renderDataCellContent($model, $key, $index)
  202. {
  203. return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) {
  204. $name = $matches[1];
  205. if (isset($this->visibleButtons[$name])) {
  206. $isVisible = $this->visibleButtons[$name] instanceof \Closure
  207. ? call_user_func($this->visibleButtons[$name], $model, $key, $index)
  208. : $this->visibleButtons[$name];
  209. } else {
  210. $isVisible = true;
  211. }
  212. if ($isVisible && isset($this->buttons[$name])) {
  213. $url = $this->createUrl($name, $model, $key, $index);
  214. return call_user_func($this->buttons[$name], $url, $model, $key);
  215. }
  216. return '';
  217. }, $this->template);
  218. }
  219. }