You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
6.3 KiB

  1. <?php
  2. /*
  3. * The MIT License
  4. *
  5. * Copyright 2019 Blobt.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. namespace blobt\grid;
  26. use Yii;
  27. use yii\helpers\Html;
  28. use yii\helpers\Url;
  29. use blobt\grid\Column;
  30. class ActionColumn extends Column {
  31. /**
  32. * @var string 处理的控制器ID
  33. */
  34. public $controller;
  35. /**
  36. * @var string 按钮模板
  37. */
  38. public $template = '{view} {update} {delete}';
  39. /**
  40. * @var array 以按钮名为键,以匿名函数为值,通过匿名函数返回html,用来控制按钮的表现形式
  41. * 匿名函数必须遵循以下申明方式:
  42. *
  43. * ```php
  44. * function ($url, $model, $key) {
  45. * // return the button HTML code
  46. * }
  47. * ```
  48. *
  49. * - `$url`: 按钮的跳转路径
  50. * - `$model`: 每行的模型
  51. * - `$key`: id值
  52. *
  53. * 使用案例:
  54. * ```php
  55. * [
  56. * 'update' => function ($url, $model, $key) {
  57. * return $model->status === 'editable' ? Html::a('Update', $url) : '';
  58. * },
  59. * ],
  60. *
  61. */
  62. public $buttons = [];
  63. /** @var array 和上述$buttons功能类似,只是匿名函数返回布尔,只控制是否展示
  64. * 匿名函数必须遵循以下申明方式:
  65. *
  66. * ```php
  67. * function ($model, $key, $index) {
  68. * return $model->status === 'editable';
  69. * }
  70. * ```
  71. *
  72. * 使用案例:
  73. * ```php
  74. * [
  75. * 'update' => \Yii::$app->user->can('update'),
  76. * ],
  77. * ```
  78. * @since 2.0.7
  79. */
  80. public $visibleButtons = [];
  81. /**
  82. * @var callable 匿名函数,用作控制按钮Url
  83. *
  84. * 匿名函数必须遵循以下申明方式:
  85. * ```php
  86. * function (string $action, mixed $model, mixed $key, integer $index, ActionColumn $this) {
  87. * //return string;
  88. * }
  89. * ```
  90. *
  91. * 如果没有设置,默认使用本类的[[createUrl()]].
  92. */
  93. public $urlCreator;
  94. /**
  95. * @var array 按钮的html属性
  96. */
  97. public $buttonOptions = [];
  98. /**
  99. * {@inheritdoc}
  100. */
  101. public function init() {
  102. parent::init();
  103. $this->initDefaultButtons();
  104. }
  105. /**
  106. * 初始化默认按钮
  107. */
  108. protected function initDefaultButtons() {
  109. $this->initDefaultButton('view', 'eye-open');
  110. $this->initDefaultButton('update', 'pencil');
  111. $this->initDefaultButton('delete', 'trash', [
  112. 'alertify-confirm' => Yii::t('yii', 'Are you sure you want to delete this item?')
  113. ]);
  114. }
  115. /**
  116. * 初始化按钮
  117. * @param string $name
  118. * @param string $iconName
  119. * @param array $additionalOptions 附加html属性
  120. */
  121. protected function initDefaultButton($name, $iconName, $additionalOptions = []) {
  122. if (!isset($this->buttons[$name]) && strpos($this->template, '{' . $name . '}') !== false) {
  123. $this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions) {
  124. switch ($name) {
  125. case 'view':
  126. $title = Yii::t('yii', 'View');
  127. break;
  128. case 'update':
  129. $title = Yii::t('yii', 'Update');
  130. break;
  131. case 'delete':
  132. $title = Yii::t('yii', 'Delete');
  133. break;
  134. default:
  135. $title = ucfirst($name);
  136. }
  137. $options = array_merge([
  138. 'title' => $title,
  139. 'aria-label' => $title,
  140. 'data-pjax' => '0',
  141. ], $additionalOptions, $this->buttonOptions);
  142. $icon = Html::tag('span', '', ['class' => "glyphicon glyphicon-$iconName"]);
  143. return Html::a($icon, $url, $options);
  144. };
  145. }
  146. }
  147. /**
  148. * 通过给定的action和model创建一个URL.
  149. *
  150. * @param string $action 按钮名
  151. * @param \yii\db\ActiveRecordInterface $model 数据模型
  152. * @param mixed $key 模型的ID
  153. * @param int $index 行号
  154. * @return string the created URL
  155. */
  156. public function createUrl($action, $model, $key, $index) {
  157. if (is_callable($this->urlCreator)) {
  158. return call_user_func($this->urlCreator, $action, $model, $key, $index, $this);
  159. }
  160. $params = is_array($key) ? $key : ['id' => (string) $key];
  161. $params[0] = $this->controller ? $this->controller . '/' . $action : $action;
  162. return Url::toRoute($params);
  163. }
  164. /**
  165. * {@inheritdoc}
  166. */
  167. protected function renderDataCellContent($model, $key, $index) {
  168. return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) {
  169. $name = $matches[1];
  170. if (isset($this->visibleButtons[$name])) {
  171. $isVisible = $this->visibleButtons[$name] instanceof \Closure ? call_user_func($this->visibleButtons[$name], $model, $key, $index) : $this->visibleButtons[$name];
  172. } else {
  173. $isVisible = true;
  174. }
  175. if ($isVisible && isset($this->buttons[$name])) {
  176. $url = $this->createUrl($name, $model, $key, $index);
  177. return call_user_func($this->buttons[$name], $url, $model, $key);
  178. }
  179. return '';
  180. }, $this->template);
  181. }
  182. }