Config.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. namespace app\admin\controller\routine;
  3. use Throwable;
  4. use ba\Filesystem;
  5. use app\common\library\Email;
  6. use PHPMailer\PHPMailer\PHPMailer;
  7. use app\common\controller\Backend;
  8. use app\admin\model\Config as ConfigModel;
  9. use PHPMailer\PHPMailer\Exception as PHPMailerException;
  10. class Config extends Backend
  11. {
  12. /**
  13. * @var object
  14. * @phpstan-var ConfigModel
  15. */
  16. protected object $model;
  17. protected array $noNeedLogin = ['index'];
  18. protected array $filePath = [
  19. 'appConfig' => 'config/app.php',
  20. 'webAdminBase' => 'web/src/router/static/adminBase.ts',
  21. 'backendEntranceStub' => 'app/admin/library/stubs/backendEntrance.stub',
  22. ];
  23. public function initialize(): void
  24. {
  25. parent::initialize();
  26. $this->model = new ConfigModel();
  27. }
  28. public function index(): void
  29. {
  30. $configGroup = get_sys_config('config_group');
  31. $config = $this->model->order('weigh desc')->select()->toArray();
  32. $list = [];
  33. $newConfigGroup = [];
  34. foreach ($configGroup as $item) {
  35. $list[$item['key']]['name'] = $item['key'];
  36. $list[$item['key']]['title'] = __($item['value']);
  37. $newConfigGroup[$item['key']] = $list[$item['key']]['title'];
  38. }
  39. foreach ($config as $item) {
  40. if (array_key_exists($item['group'], $newConfigGroup)) {
  41. $item['title'] = __($item['title']);
  42. $list[$item['group']]['list'][] = $item;
  43. }
  44. }
  45. $this->success('', [
  46. 'list' => $list,
  47. 'remark' => get_route_remark(),
  48. 'configGroup' => $newConfigGroup ?? [],
  49. 'quickEntrance' => get_sys_config('config_quick_entrance'),
  50. ]);
  51. }
  52. /**
  53. * 编辑
  54. * @throws Throwable
  55. */
  56. public function edit(): void
  57. {
  58. $all = $this->model->select();
  59. foreach ($all as $item) {
  60. if ($item['type'] == 'editor') {
  61. $this->request->filter('clean_xss');
  62. break;
  63. }
  64. }
  65. if ($this->request->isPost()) {
  66. $this->modelValidate = false;
  67. $data = $this->request->post();
  68. if (!$data) {
  69. $this->error(__('Parameter %s can not be empty', ['']));
  70. }
  71. $data = $this->excludeFields($data);
  72. $configValue = [];
  73. foreach ($all as $item) {
  74. if (array_key_exists($item->name, $data)) {
  75. $configValue[] = [
  76. 'id' => $item->id,
  77. 'type' => $item->getData('type'),
  78. 'value' => $data[$item->name]
  79. ];
  80. // 自定义后台入口
  81. if ($item->name == 'backend_entrance') {
  82. $backendEntrance = get_sys_config('backend_entrance');
  83. if ($backendEntrance == $data[$item->name]) continue;
  84. if (!preg_match("/^\/[a-zA-Z0-9]+$/", $data[$item->name])) {
  85. $this->error(__('Backend entrance rule'));
  86. }
  87. // 修改 adminBaseRoutePath
  88. $adminBaseFilePath = Filesystem::fsFit(root_path() . $this->filePath['webAdminBase']);
  89. $adminBaseContent = @file_get_contents($adminBaseFilePath);
  90. if (!$adminBaseContent) $this->error(__('Configuration write failed: %s', [$this->filePath['webAdminBase']]));
  91. $adminBaseContent = str_replace("export const adminBaseRoutePath = '$backendEntrance'", "export const adminBaseRoutePath = '{$data[$item->name]}'", $adminBaseContent);
  92. $result = @file_put_contents($adminBaseFilePath, $adminBaseContent);
  93. if (!$result) $this->error(__('Configuration write failed: %s', [$this->filePath['webAdminBase']]));
  94. // 去除后台入口开头的斜杠
  95. $oldBackendEntrance = ltrim($backendEntrance, '/');
  96. $newBackendEntrance = ltrim($data[$item->name], '/');
  97. // 设置应用别名映射
  98. $appMap = config('app.app_map');
  99. $adminMapKey = array_search('admin', $appMap);
  100. if ($adminMapKey !== false) {
  101. unset($appMap[$adminMapKey]);
  102. }
  103. if ($newBackendEntrance != 'admin') {
  104. $appMap[$newBackendEntrance] = 'admin';
  105. }
  106. $appConfigFilePath = Filesystem::fsFit(root_path() . $this->filePath['appConfig']);
  107. $appConfigContent = @file_get_contents($appConfigFilePath);
  108. if (!$appConfigContent) $this->error(__('Configuration write failed: %s', [$this->filePath['appConfig']]));
  109. $appMapStr = '';
  110. foreach ($appMap as $newAppName => $oldAppName) {
  111. $appMapStr .= "'$newAppName' => '$oldAppName', ";
  112. }
  113. $appMapStr = rtrim($appMapStr, ', ');
  114. $appMapStr = "[$appMapStr]";
  115. $appConfigContent = preg_replace("/'app_map'(\s+)=>(\s+)(.*)\/\/ 域名/s", "'app_map'\$1=>\$2$appMapStr,\n // 域名", $appConfigContent);
  116. $result = @file_put_contents($appConfigFilePath, $appConfigContent);
  117. if (!$result) $this->error(__('Configuration write failed: %s', [$this->filePath['appConfig']]));
  118. // 建立API入口文件
  119. $oldBackendEntranceFile = Filesystem::fsFit(public_path() . $oldBackendEntrance . '.php');
  120. $newBackendEntranceFile = Filesystem::fsFit(public_path() . $newBackendEntrance . '.php');
  121. if (file_exists($oldBackendEntranceFile)) @unlink($oldBackendEntranceFile);
  122. if ($newBackendEntrance != 'admin') {
  123. $backendEntranceStub = @file_get_contents(Filesystem::fsFit(root_path() . $this->filePath['backendEntranceStub']));
  124. if (!$backendEntranceStub) $this->error(__('Configuration write failed: %s', [$this->filePath['backendEntranceStub']]));
  125. $result = @file_put_contents($newBackendEntranceFile, $backendEntranceStub);
  126. if (!$result) $this->error(__('Configuration write failed: %s', [$newBackendEntranceFile]));
  127. }
  128. }
  129. }
  130. }
  131. $result = false;
  132. $this->model->startTrans();
  133. try {
  134. // 模型验证
  135. if ($this->modelValidate) {
  136. $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
  137. if (class_exists($validate)) {
  138. $validate = new $validate();
  139. if ($this->modelSceneValidate) $validate->scene('edit');
  140. $validate->check($data);
  141. }
  142. }
  143. $result = $this->model->saveAll($configValue);
  144. $this->model->commit();
  145. } catch (Throwable $e) {
  146. $this->model->rollback();
  147. $this->error($e->getMessage());
  148. }
  149. if ($result !== false) {
  150. $this->success(__('The current page configuration item was updated successfully'));
  151. } else {
  152. $this->error(__('No rows updated'));
  153. }
  154. }
  155. }
  156. public function add(): void
  157. {
  158. if ($this->request->isPost()) {
  159. $data = $this->request->post();
  160. if (!$data) {
  161. $this->error(__('Parameter %s can not be empty', ['']));
  162. }
  163. $data = $this->excludeFields($data);
  164. $result = false;
  165. $this->model->startTrans();
  166. try {
  167. // 模型验证
  168. if ($this->modelValidate) {
  169. $validate = str_replace("\\model\\", "\\validate\\", get_class($this->model));
  170. if (class_exists($validate)) {
  171. $validate = new $validate();
  172. if ($this->modelSceneValidate) $validate->scene('add');
  173. $validate->check($data);
  174. }
  175. }
  176. $result = $this->model->save($data);
  177. $this->model->commit();
  178. } catch (Throwable $e) {
  179. $this->model->rollback();
  180. $this->error($e->getMessage());
  181. }
  182. if ($result !== false) {
  183. $this->success(__('Added successfully'));
  184. } else {
  185. $this->error(__('No rows were added'));
  186. }
  187. }
  188. $this->error(__('Parameter error'));
  189. }
  190. /**
  191. * 发送邮件测试
  192. * @throws Throwable
  193. */
  194. public function sendTestMail(): void
  195. {
  196. $data = $this->request->post();
  197. $mail = new Email();
  198. try {
  199. $mail->Host = $data['smtp_server'];
  200. $mail->SMTPAuth = true;
  201. $mail->Username = $data['smtp_user'];
  202. $mail->Password = $data['smtp_pass'];
  203. $mail->SMTPSecure = $data['smtp_verification'] == 'SSL' ? PHPMailer::ENCRYPTION_SMTPS : PHPMailer::ENCRYPTION_STARTTLS;
  204. $mail->Port = $data['smtp_port'];
  205. $mail->setFrom($data['smtp_sender_mail'], $data['smtp_user']);
  206. $mail->isSMTP();
  207. $mail->addAddress($data['testMail']);
  208. $mail->isHTML();
  209. $mail->setSubject(__('This is a test email') . '-' . get_sys_config('site_name'));
  210. $mail->Body = __('Congratulations, receiving this email means that your email service has been configured correctly');
  211. $mail->send();
  212. } catch (PHPMailerException) {
  213. $this->error($mail->ErrorInfo);
  214. }
  215. $this->success(__('Test mail sent successfully~'));
  216. }
  217. }