Command.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. namespace app\admin\controller;
  3. use app\common\controller\Backend;
  4. use think\Config;
  5. use think\console\Input;
  6. use think\Db;
  7. use think\Exception;
  8. /**
  9. * 在线命令管理
  10. *
  11. * @icon fa fa-circle-o
  12. */
  13. class Command extends Backend
  14. {
  15. /**
  16. * Command模型对象
  17. */
  18. protected $model = null;
  19. protected $noNeedRight = ['get_controller_list', 'get_field_list'];
  20. public function _initialize()
  21. {
  22. parent::_initialize();
  23. $this->model = new \app\admin\model\Command;
  24. $this->view->assign("statusList", $this->model->getStatusList());
  25. }
  26. /**
  27. * 添加
  28. */
  29. public function add()
  30. {
  31. $tableList = [];
  32. $list = \think\Db::query("SHOW TABLES");
  33. foreach ($list as $key => $row) {
  34. $tableList[reset($row)] = reset($row);
  35. }
  36. $this->view->assign("tableList", $tableList);
  37. return $this->view->fetch();
  38. }
  39. /**
  40. * 获取字段列表
  41. * @internal
  42. */
  43. public function get_field_list()
  44. {
  45. $dbname = Config::get('database.database');
  46. $prefix = Config::get('database.prefix');
  47. $table = $this->request->request('table');
  48. //从数据库中获取表字段信息
  49. $sql = "SELECT * FROM `information_schema`.`columns` "
  50. . "WHERE TABLE_SCHEMA = ? AND table_name = ? "
  51. . "ORDER BY ORDINAL_POSITION";
  52. //加载主表的列
  53. $columnList = Db::query($sql, [$dbname, $table]);
  54. $fieldlist = [];
  55. foreach ($columnList as $index => $item) {
  56. $fieldlist[] = $item['COLUMN_NAME'];
  57. }
  58. $this->success("", null, ['fieldlist' => $fieldlist]);
  59. }
  60. /**
  61. * 获取控制器列表
  62. * @internal
  63. */
  64. public function get_controller_list()
  65. {
  66. //搜索关键词,客户端输入以空格分开,这里接收为数组
  67. $word = (array)$this->request->request("q_word/a");
  68. $word = implode('', $word);
  69. $adminPath = dirname(__DIR__) . DS;
  70. $controllerDir = $adminPath . 'controller' . DS;
  71. $files = new \RecursiveIteratorIterator(
  72. new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
  73. );
  74. $list = [];
  75. foreach ($files as $name => $file) {
  76. if (!$file->isDir()) {
  77. $filePath = $file->getRealPath();
  78. $name = str_replace($controllerDir, '', $filePath);
  79. $name = str_replace(DS, "/", $name);
  80. if (!preg_match("/(.*)\.php\$/", $name)) {
  81. continue;
  82. }
  83. if (!$word || stripos($name, $word) !== false) {
  84. $list[] = ['id' => $name, 'name' => $name];
  85. }
  86. }
  87. }
  88. $pageNumber = $this->request->request("pageNumber");
  89. $pageSize = $this->request->request("pageSize");
  90. return json(['list' => array_slice($list, ($pageNumber - 1) * $pageSize, $pageSize), 'total' => count($list)]);
  91. }
  92. /**
  93. * 详情
  94. */
  95. public function detail($ids)
  96. {
  97. $row = $this->model->get($ids);
  98. if (!$row) {
  99. $this->error(__('No Results were found'));
  100. }
  101. $this->view->assign("row", $row);
  102. return $this->view->fetch();
  103. }
  104. /**
  105. * 执行
  106. */
  107. public function execute($ids)
  108. {
  109. $row = $this->model->get($ids);
  110. if (!$row) {
  111. $this->error(__('No Results were found'));
  112. }
  113. $result = $this->doexecute($row['type'], json_decode($row['params'], true));
  114. $this->success("", null, ['result' => $result]);
  115. }
  116. /**
  117. * 生成命令
  118. */
  119. public function command($action = '')
  120. {
  121. $commandtype = $this->request->request("commandtype");
  122. $params = $this->request->request();
  123. $allowfields = [
  124. 'crud' => 'table,controller,model,fields,force,local,delete,menu',
  125. 'menu' => 'controller,delete',
  126. 'min' => 'module,resource,optimize',
  127. 'api' => 'url,module,output,template,force,title,author,class,language,addon',
  128. ];
  129. $argv = [];
  130. $allowfields = isset($allowfields[$commandtype]) ? explode(',', $allowfields[$commandtype]) : [];
  131. $allowfields = array_filter(array_intersect_key($params, array_flip($allowfields)));
  132. if (isset($params['local']) && !$params['local']) {
  133. $allowfields['local'] = $params['local'];
  134. } else {
  135. unset($allowfields['local']);
  136. }
  137. foreach ($allowfields as $key => $param) {
  138. $argv[] = "--{$key}=" . (is_array($param) ? implode(',', $param) : $param);
  139. }
  140. if ($commandtype == 'crud') {
  141. $extend = 'setcheckboxsuffix,enumradiosuffix,imagefield,filefield,intdatesuffix,switchsuffix,citysuffix,selectpagesuffix,selectpagessuffix,ignorefields,sortfield,editorsuffix,headingfilterfield,tagsuffix,jsonsuffix,fixedcolumns';
  142. $extendArr = explode(',', $extend);
  143. foreach ($params as $index => $item) {
  144. if (in_array($index, $extendArr)) {
  145. foreach (explode(',', $item) as $key => $value) {
  146. if ($value) {
  147. $argv[] = "--{$index}={$value}";
  148. }
  149. }
  150. }
  151. }
  152. $isrelation = (int)$this->request->request('isrelation');
  153. if ($isrelation && isset($params['relation'])) {
  154. foreach ($params['relation'] as $index => $relation) {
  155. foreach ($relation as $key => $value) {
  156. $argv[] = "--{$key}=" . (is_array($value) ? implode(',', $value) : $value);
  157. }
  158. }
  159. }
  160. } else {
  161. if ($commandtype == 'menu') {
  162. if (isset($params['allcontroller']) && $params['allcontroller']) {
  163. $argv[] = "--controller=all-controller";
  164. } else {
  165. foreach (explode(',', $params['controllerfile']) as $index => $param) {
  166. if ($param) {
  167. $argv[] = "--controller=" . substr($param, 0, -4);
  168. }
  169. }
  170. }
  171. } else {
  172. if ($commandtype == 'min') {
  173. } else {
  174. if ($commandtype == 'api') {
  175. } else {
  176. }
  177. }
  178. }
  179. }
  180. if ($action == 'execute') {
  181. if (stripos(implode(' ', $argv), '--controller=all-controller') !== false) {
  182. $this->error("只允许在命令行执行该命令,执行前请做好菜单规则备份!!!");
  183. }
  184. if (config('app_debug')) {
  185. $result = $this->doexecute($commandtype, $argv);
  186. $this->success("", null, ['result' => $result]);
  187. } else {
  188. $this->error("只允许在开发环境下执行命令");
  189. }
  190. } else {
  191. $this->success("", null, ['command' => "php think {$commandtype} " . implode(' ', $argv)]);
  192. }
  193. return;
  194. }
  195. protected function doexecute($commandtype, $argv)
  196. {
  197. if (!config('app_debug')) {
  198. $this->error("只允许在开发环境下执行命令");
  199. }
  200. if (preg_match("/([;\|&]+)/", implode(' ', $argv))) {
  201. $this->error("不支持的命令参数");
  202. }
  203. $commandName = "\\app\\admin\\command\\" . ucfirst($commandtype);
  204. $input = new Input($argv);
  205. $output = new \addons\command\library\Output();
  206. $command = new $commandName($commandtype);
  207. $data = [
  208. 'type' => $commandtype,
  209. 'params' => json_encode($argv),
  210. 'command' => "php think {$commandtype} " . implode(' ', $argv),
  211. 'executetime' => time(),
  212. ];
  213. $this->model->save($data);
  214. try {
  215. $command->run($input, $output);
  216. $result = implode("\n", $output->getMessage());
  217. $this->model->status = 'successed';
  218. } catch (Exception $e) {
  219. $result = implode("\n", $output->getMessage()) . "\n";
  220. $result .= $e->getMessage();
  221. $this->model->status = 'failured';
  222. }
  223. $result = trim($result);
  224. $this->model->content = $result;
  225. $this->model->save();
  226. return $result;
  227. }
  228. }