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.

277 lines
8.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 iron\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. /**
  33. * @var array 配置按钮配置,通过配置参数控制按钮的标题,url,图标以及确认框内容和隐藏条件
  34. *
  35. * ```php
  36. *
  37. * - `$title`: 按钮的标题
  38. * - `$name`: 按钮的跳转路径
  39. * - `$icon`: 按钮图标
  40. * - `$contents`: 确认框内容
  41. * - `$hide`: array 隐藏条件
  42. *
  43. * 使用案例:
  44. * ```php
  45. * [
  46. * 'name' => 'delete',
  47. * 'icon' => 'trash',
  48. * 'title' => '删除',
  49. * 'contents' => '确定删除?'
  50. * //attributes 和 values 两数组对应元素按规则匹配成功时候隐藏该按钮
  51. * 'hide'=>[
  52. * 'attributes'=>['status'],//模型属性
  53. * 'values'=>[1],//属性值
  54. * 'rule'=>'or' //与或规则 只填 or 或 and
  55. * ]
  56. * ]
  57. *
  58. */
  59. public $config = [
  60. [
  61. 'name' => 'view',
  62. 'icon' => 'list',
  63. 'title' => '详情',
  64. ],
  65. [
  66. 'name' => 'update',
  67. 'icon' => 'pencil',
  68. 'title' => '修改'
  69. ],
  70. [
  71. 'name' => 'delete',
  72. 'icon' => 'trash',
  73. 'title' => '删除',
  74. 'contents' => '确定删除?'
  75. ]
  76. ];
  77. /**
  78. * @var string 处理的控制器ID
  79. */
  80. public $controller;
  81. /**
  82. * @var string 按钮模板
  83. */
  84. public $template = '';
  85. /**
  86. * @var array 以按钮名为键,以匿名函数为值,通过匿名函数返回html,用来控制按钮的表现形式
  87. * 匿名函数必须遵循以下申明方式:
  88. *
  89. * ```php
  90. * function ($url, $model, $key) {
  91. * // return the button HTML code
  92. * }
  93. * ```
  94. *
  95. * - `$url`: 按钮的跳转路径
  96. * - `$model`: 每行的模型
  97. * - `$key`: id值
  98. *
  99. * 使用案例:
  100. * ```php
  101. * [
  102. * 'update' => function ($url, $model, $key) {
  103. * return $model->status === 'editable' ? Html::a('Update', $url) : '';
  104. * },
  105. * ],
  106. *
  107. */
  108. public $buttons = [];
  109. /** @var array 和上述$buttons功能类似,只是匿名函数返回布尔,只控制是否展示
  110. * 匿名函数必须遵循以下申明方式:
  111. *
  112. * ```php
  113. * function ($model, $key, $index) {
  114. * return $model->status === 'editable';
  115. * }
  116. * ```
  117. *
  118. * 使用案例:
  119. * ```php
  120. * [
  121. * 'update' => \Yii::$app->user->can('update'),
  122. * ],
  123. * ```
  124. * @since 2.0.7
  125. */
  126. public $visibleButtons = [];
  127. /**
  128. * @var callable 匿名函数,用作控制按钮Url
  129. *
  130. * 匿名函数必须遵循以下申明方式:
  131. * ```php
  132. * function (string $action, mixed $model, mixed $key, integer $index, ActionColumn $this) {
  133. * //return string;
  134. * }
  135. * ```
  136. *
  137. * 如果没有设置,默认使用本类的[[createUrl()]].
  138. */
  139. public $urlCreator;
  140. /**
  141. * @var array 按钮的html属性
  142. */
  143. public $buttonOptions = [];
  144. /**
  145. * {@inheritdoc}
  146. */
  147. public function init()
  148. {
  149. parent::init();
  150. foreach ($this->config as $config) {
  151. if (isset($config['contents'])) {
  152. $options = ['alertify-confirm' => Yii::t('yii', "{$config['contents']}?")];
  153. } else {
  154. $options = [];
  155. }
  156. if (isset($config['icon'])) {
  157. $icon = $config['icon'];
  158. } else {
  159. $icon = 'th-large';
  160. }
  161. if (isset($config['title'])) {
  162. $title = $config['title'];
  163. } else {
  164. $title = $config['name'];
  165. }
  166. if (isset($config['hide'])) {
  167. $this->visibleButtons($config['name'], $config['hide']);
  168. }
  169. $this->initButton($config['name'], $icon, $options, $title);
  170. $this->template .= " {{$config['name']}}";
  171. }
  172. }
  173. /**
  174. * 初始化按钮
  175. * @param string $name
  176. * @param string $iconName
  177. * @param array $additionalOptions 附加html属性
  178. */
  179. protected function initButton($name, $iconName, $additionalOptions = [], $title = '')
  180. {
  181. $this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions, $title) {
  182. $title = $title ?: Yii::t('yii', $name);
  183. $options = array_merge([
  184. 'title' => $title,
  185. 'aria-label' => $title,
  186. 'data-pjax' => '0',
  187. ], $additionalOptions, $this->buttonOptions);
  188. $icon = Html::tag('span', '', ['class' => "oi oi-$iconName"]);
  189. return Html::a($icon, $url, $options);
  190. };
  191. }
  192. /**
  193. * @param string $name
  194. * @param array $config 隐藏配置
  195. * 验证按钮的显示隐藏规则
  196. */
  197. protected function visibleButtons($name, $config)
  198. {
  199. $this->visibleButtons[$name] = function ($model, $key, $index) use ($config) {
  200. $attributes = $config['attributes'];
  201. $values = $config['values'];
  202. if (isset($config['rule']) && $config['rule'] == 'or') {
  203. foreach ($attributes as $k => $attribute) {
  204. if ($model->$attribute == $values[$k]) {
  205. return false;
  206. }
  207. }
  208. return true;
  209. }else{
  210. foreach ($attributes as $k => $attribute) {
  211. if ($model->$attribute != $values[$k]) {
  212. return true;
  213. }
  214. }
  215. return false;
  216. }
  217. };
  218. }
  219. /**
  220. * 通过给定的action和model创建一个URL.
  221. *
  222. * @param string $action 按钮名
  223. * @param \yii\db\ActiveRecordInterface $model 数据模型
  224. * @param mixed $key 模型的ID
  225. * @param int $index 行号
  226. * @return string the created URL
  227. */
  228. public function createUrl($action, $model, $key, $index)
  229. {
  230. if (is_callable($this->urlCreator)) {
  231. return call_user_func($this->urlCreator, $action, $model, $key, $index, $this);
  232. }
  233. $params = is_array($key) ? $key : ['id' => (string)$key];
  234. $params[0] = $this->controller ? $this->controller . '/' . $action : $action;
  235. return Url::toRoute($params);
  236. }
  237. /**
  238. * {@inheritdoc}
  239. */
  240. protected function renderDataCellContent($model, $key, $index)
  241. {
  242. return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) {
  243. $name = $matches[1];
  244. if (isset($this->visibleButtons[$name])) {
  245. $isVisible = $this->visibleButtons[$name] instanceof \Closure ? call_user_func($this->visibleButtons[$name], $model, $key, $index) : $this->visibleButtons[$name];
  246. } else {
  247. $isVisible = true;
  248. }
  249. if ($isVisible && isset($this->buttons[$name])) {
  250. $url = $this->createUrl($name, $model, $key, $index);
  251. return call_user_func($this->buttons[$name], $url, $model, $key);
  252. }
  253. return '';
  254. }, $this->template);
  255. }
  256. }