StorageConfigService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. <?php
  2. namespace App\Module\File\Services;
  3. use App\Module\File\Models\FileStorageConfig;
  4. use App\Module\File\Models\FileStorageConfigHistory;
  5. use Illuminate\Support\Facades\Cache;
  6. use Illuminate\Support\Facades\Log;
  7. /**
  8. * 存储配置服务类
  9. *
  10. * 提供存储配置的业务逻辑处理,包括配置的读取、更新和缓存管理
  11. */
  12. class StorageConfigService
  13. {
  14. /**
  15. * 缓存前缀
  16. */
  17. const CACHE_PREFIX = 'file_storage_config:';
  18. /**
  19. * 缓存过期时间(秒)
  20. */
  21. const CACHE_TTL = 3600; // 1小时
  22. /**
  23. * 获取默认存储磁盘配置
  24. *
  25. * @return FileStorageConfig|null 存储配置模型
  26. */
  27. public function getDefaultDisk()
  28. {
  29. return Cache::remember(self::CACHE_PREFIX . 'default:' . app()->environment(), self::CACHE_TTL, function () {
  30. return FileStorageConfig::where('is_default', true)
  31. ->where('status', true)
  32. ->where('env', app()->environment())
  33. ->first();
  34. });
  35. }
  36. /**
  37. * 获取临时存储磁盘配置
  38. *
  39. * @return FileStorageConfig|null 存储配置模型
  40. */
  41. public function getTempDisk()
  42. {
  43. return Cache::remember(self::CACHE_PREFIX . 'temp:' . app()->environment(), self::CACHE_TTL, function () {
  44. return FileStorageConfig::where('is_temp', true)
  45. ->where('status', true)
  46. ->where('env', app()->environment())
  47. ->first();
  48. });
  49. }
  50. /**
  51. * 获取指定名称的存储磁盘配置
  52. *
  53. * @param string $name 存储磁盘名称
  54. * @return FileStorageConfig|null 存储配置模型
  55. */
  56. public function getDisk(string $name)
  57. {
  58. return Cache::remember(self::CACHE_PREFIX . 'name:' . $name . ':' . app()->environment(), self::CACHE_TTL, function () use ($name) {
  59. return FileStorageConfig::where('name', $name)
  60. ->where('status', true)
  61. ->where('env', app()->environment())
  62. ->first();
  63. });
  64. }
  65. /**
  66. * 获取所有启用的存储磁盘配置
  67. *
  68. * @param string|null $env 环境名称,为null时获取当前环境
  69. * @return \Illuminate\Database\Eloquent\Collection 存储配置集合
  70. */
  71. public function getAllDisks(string $env = null)
  72. {
  73. $env = $env ?: app()->environment();
  74. return Cache::remember(self::CACHE_PREFIX . 'all:' . $env, self::CACHE_TTL, function () use ($env) {
  75. return FileStorageConfig::where('status', true)
  76. ->where('env', $env)
  77. ->get();
  78. });
  79. }
  80. /**
  81. * 创建存储磁盘配置
  82. *
  83. * @param string $name 存储磁盘名称
  84. * @param string $driver 存储驱动
  85. * @param array $config 配置值
  86. * @param string $description 配置描述
  87. * @param bool $isDefault 是否默认存储
  88. * @param bool $isTemp 是否用于临时存储
  89. * @param string $env 环境名称
  90. * @param int $createdBy 创建人ID
  91. * @return FileStorageConfig 存储配置模型
  92. */
  93. public function createDisk(string $name, string $driver, array $config, string $description = '', bool $isDefault = false, bool $isTemp = false, string $env = 'production', int $createdBy = 0)
  94. {
  95. // 如果设置为默认存储,则将其他配置的默认标志设为false
  96. if ($isDefault) {
  97. $this->resetDefaultFlag($env);
  98. }
  99. // 如果设置为临时存储,则将其他配置的临时标志设为false
  100. if ($isTemp) {
  101. $this->resetTempFlag($env);
  102. }
  103. $storageConfig = new FileStorageConfig();
  104. $storageConfig->name = $name;
  105. $storageConfig->driver = $driver;
  106. $storageConfig->config = $config;
  107. $storageConfig->description = $description;
  108. $storageConfig->is_default = $isDefault;
  109. $storageConfig->is_temp = $isTemp;
  110. $storageConfig->env = $env;
  111. $storageConfig->status = true;
  112. $storageConfig->created_by = $createdBy;
  113. $storageConfig->updated_by = $createdBy;
  114. $storageConfig->save();
  115. // 清除缓存
  116. $this->clearCache();
  117. return $storageConfig;
  118. }
  119. /**
  120. * 更新存储磁盘配置
  121. *
  122. * @param int $id 存储配置ID
  123. * @param string $driver 存储驱动
  124. * @param array $config 配置值
  125. * @param string $description 配置描述
  126. * @param bool $isDefault 是否默认存储
  127. * @param bool $isTemp 是否用于临时存储
  128. * @param int $status 状态
  129. * @param int $updatedBy 更新人ID
  130. * @param string $reason 变更原因
  131. * @return FileStorageConfig 存储配置模型
  132. */
  133. public function updateDisk(int $id, string $driver, array $config, string $description = '', bool $isDefault = false, bool $isTemp = false, int $status = 1, int $updatedBy = 0, string $reason = '')
  134. {
  135. $storageConfig = FileStorageConfig::findOrFail($id);
  136. $oldData = $storageConfig->toArray();
  137. // 如果设置为默认存储,则将其他配置的默认标志设为false
  138. if ($isDefault && !$storageConfig->is_default) {
  139. $this->resetDefaultFlag($storageConfig->env);
  140. }
  141. // 如果设置为临时存储,则将其他配置的临时标志设为false
  142. if ($isTemp && !$storageConfig->is_temp) {
  143. $this->resetTempFlag($storageConfig->env);
  144. }
  145. $storageConfig->driver = $driver;
  146. $storageConfig->config = $config;
  147. $storageConfig->description = $description;
  148. $storageConfig->is_default = $isDefault;
  149. $storageConfig->is_temp = $isTemp;
  150. $storageConfig->status = (bool)$status;
  151. $storageConfig->updated_by = $updatedBy;
  152. $storageConfig->save();
  153. // 记录变更历史
  154. $this->recordHistory($id, $oldData, $storageConfig->toArray(), $updatedBy, $reason);
  155. // 清除缓存
  156. $this->clearCache();
  157. return $storageConfig;
  158. }
  159. /**
  160. * 删除存储磁盘配置
  161. *
  162. * @param int $id 存储配置ID
  163. * @param int $deletedBy 删除人ID
  164. * @param string $reason 删除原因
  165. * @return bool 是否成功
  166. */
  167. public function deleteDisk(int $id, int $deletedBy = 0, string $reason = '')
  168. {
  169. $storageConfig = FileStorageConfig::findOrFail($id);
  170. $oldData = $storageConfig->toArray();
  171. // 记录删除历史
  172. $this->recordHistory($id, $oldData, [], $deletedBy, $reason ?: '删除配置');
  173. $result = $storageConfig->delete();
  174. // 清除缓存
  175. $this->clearCache();
  176. return $result;
  177. }
  178. /**
  179. * 设置默认存储磁盘
  180. *
  181. * @param int $id 存储配置ID
  182. * @param int $updatedBy 更新人ID
  183. * @return bool 是否成功
  184. */
  185. public function setDefaultDisk(int $id, int $updatedBy = 0)
  186. {
  187. $storageConfig = FileStorageConfig::findOrFail($id);
  188. $oldData = $storageConfig->toArray();
  189. // 重置当前环境中的所有默认标志
  190. $this->resetDefaultFlag($storageConfig->env);
  191. // 设置当前配置为默认
  192. $storageConfig->is_default = true;
  193. $storageConfig->updated_by = $updatedBy;
  194. $result = $storageConfig->save();
  195. // 记录变更历史
  196. $this->recordHistory($id, $oldData, $storageConfig->toArray(), $updatedBy, '设置为默认存储磁盘');
  197. // 清除缓存
  198. $this->clearCache();
  199. return $result;
  200. }
  201. /**
  202. * 设置临时存储磁盘
  203. *
  204. * @param int $id 存储配置ID
  205. * @param int $updatedBy 更新人ID
  206. * @return bool 是否成功
  207. */
  208. public function setTempDisk(int $id, int $updatedBy = 0)
  209. {
  210. $storageConfig = FileStorageConfig::findOrFail($id);
  211. $oldData = $storageConfig->toArray();
  212. // 重置当前环境中的所有临时标志
  213. $this->resetTempFlag($storageConfig->env);
  214. // 设置当前配置为临时存储
  215. $storageConfig->is_temp = true;
  216. $storageConfig->updated_by = $updatedBy;
  217. $result = $storageConfig->save();
  218. // 记录变更历史
  219. $this->recordHistory($id, $oldData, $storageConfig->toArray(), $updatedBy, '设置为临时存储磁盘');
  220. // 清除缓存
  221. $this->clearCache();
  222. return $result;
  223. }
  224. /**
  225. * 获取存储磁盘配置变更历史
  226. *
  227. * @param int $configId 存储配置ID
  228. * @return \Illuminate\Database\Eloquent\Collection 配置历史集合
  229. */
  230. public function getHistory(int $configId)
  231. {
  232. return FileStorageConfigHistory::where('config_id', $configId)
  233. ->orderBy('id', 'desc')
  234. ->get();
  235. }
  236. /**
  237. * 清除存储配置缓存
  238. *
  239. * @return void
  240. */
  241. public function clearCache()
  242. {
  243. $cacheKeys = [
  244. self::CACHE_PREFIX . 'default:' . app()->environment(),
  245. self::CACHE_PREFIX . 'temp:' . app()->environment(),
  246. self::CACHE_PREFIX . 'all:' . app()->environment()
  247. ];
  248. foreach ($cacheKeys as $key) {
  249. Cache::forget($key);
  250. }
  251. // 清除所有名称缓存
  252. $disks = FileStorageConfig::where('env', app()->environment())->get();
  253. foreach ($disks as $disk) {
  254. Cache::forget(self::CACHE_PREFIX . 'name:' . $disk->name . ':' . app()->environment());
  255. }
  256. Log::info('存储配置缓存已清除');
  257. }
  258. /**
  259. * 重置默认存储标志
  260. *
  261. * @param string $env 环境名称
  262. * @return void
  263. */
  264. protected function resetDefaultFlag(string $env)
  265. {
  266. FileStorageConfig::where('env', $env)
  267. ->where('is_default', true)
  268. ->update(['is_default' => false]);
  269. }
  270. /**
  271. * 重置临时存储标志
  272. *
  273. * @param string $env 环境名称
  274. * @return void
  275. */
  276. protected function resetTempFlag(string $env)
  277. {
  278. FileStorageConfig::where('env', $env)
  279. ->where('is_temp', true)
  280. ->update(['is_temp' => false]);
  281. }
  282. /**
  283. * 记录存储配置变更历史
  284. *
  285. * @param int $configId 存储配置ID
  286. * @param array $oldData 旧数据
  287. * @param array $newData 新数据
  288. * @param int $changedBy 变更人ID
  289. * @param string $reason 变更原因
  290. * @return FileStorageConfigHistory 配置历史模型
  291. */
  292. protected function recordHistory(int $configId, array $oldData, array $newData, int $changedBy, string $reason = '')
  293. {
  294. return FileStorageConfigHistory::create([
  295. 'config_id' => $configId,
  296. 'old_driver' => $oldData['driver'] ?? null,
  297. 'new_driver' => $newData['driver'] ?? null,
  298. 'old_config' => isset($oldData['config']) ? $oldData['config'] : null,
  299. 'new_config' => isset($newData['config']) ? $newData['config'] : null,
  300. 'old_status' => $oldData['status'] ?? null,
  301. 'new_status' => $newData['status'] ?? null,
  302. 'changed_by' => $changedBy,
  303. 'change_reason' => $reason,
  304. ]);
  305. }
  306. /**
  307. * 测试存储配置连接
  308. *
  309. * @param string $driver 存储驱动
  310. * @param array $config 配置值
  311. * @return array 测试结果,包含success和message字段
  312. */
  313. public function testConnection(string $driver, array $config)
  314. {
  315. try {
  316. // 创建临时磁盘配置
  317. $diskName = 'temp_test_' . time();
  318. $fullConfig = array_merge(['driver' => $driver], $config);
  319. config(["filesystems.disks.{$diskName}" => $fullConfig]);
  320. // 测试连接
  321. $disk = \Storage::disk($diskName);
  322. $testFile = 'test_' . time() . '.txt';
  323. $disk->put($testFile, 'Testing connection at ' . now());
  324. $content = $disk->get($testFile);
  325. $disk->delete($testFile);
  326. return [
  327. 'success' => true,
  328. 'message' => '连接成功!测试文件已成功创建和删除。',
  329. ];
  330. } catch (\Exception $e) {
  331. Log::error('存储配置连接测试失败', [
  332. 'driver' => $driver,
  333. 'config' => $config,
  334. 'error' => $e->getMessage(),
  335. ]);
  336. return [
  337. 'success' => false,
  338. 'message' => '连接失败:' . $e->getMessage(),
  339. ];
  340. }
  341. }
  342. /**
  343. * 注册存储配置到Laravel文件系统
  344. *
  345. * @return void
  346. */
  347. public function registerStorageConfigs()
  348. {
  349. $disks = $this->getAllDisks();
  350. foreach ($disks as $disk) {
  351. $config = array_merge(['driver' => $disk->driver], $disk->config);
  352. config(["filesystems.disks.{$disk->name}" => $config]);
  353. }
  354. // 设置默认磁盘
  355. $defaultDisk = $this->getDefaultDisk();
  356. if ($defaultDisk) {
  357. config(['filesystems.default' => $defaultDisk->name]);
  358. }
  359. }
  360. }