UpgradeDict.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Models\DictInfo;
  4. use App\Models\UserDict;
  5. use App\Tools\Tools;
  6. use Illuminate\Console\Command;
  7. use Illuminate\Support\Facades\Cache;
  8. use Illuminate\Support\Facades\Storage;
  9. use Illuminate\Support\Str;
  10. class UpgradeDict extends Command
  11. {
  12. /**
  13. * The name and signature of the console command.
  14. * php artisan upgrade:dict
  15. *
  16. * @var string
  17. */
  18. protected $signature = 'upgrade:dict {uuid?} {--part}';
  19. /**
  20. * The console command description.
  21. *
  22. * @var string
  23. */
  24. protected $description = '导入csv字典';
  25. protected $dictInfo;
  26. protected $cols;
  27. /**
  28. * Create a new command instance.
  29. *
  30. * @return void
  31. */
  32. public function __construct()
  33. {
  34. parent::__construct();
  35. }
  36. private function scanDict(string $dir)
  37. {
  38. if (is_dir($dir)) {
  39. $this->info('scan:'.$dir);
  40. if ($files = scandir($dir)) {
  41. // 进入目录搜索字典或子目录
  42. foreach ($files as $file) {
  43. // 进入语言目录循环搜索
  44. $fullPath = $dir.'/'.$file;
  45. if (is_dir($fullPath) && $file !== '.' && $file !== '..') {
  46. // 是目录继续搜索
  47. $this->scanDict($fullPath);
  48. } else {
  49. // 是文件,查看是否是字典信息文件
  50. $infoFile = $fullPath;
  51. if (pathinfo($infoFile, PATHINFO_EXTENSION) === 'ini') {
  52. $this->dictInfo = parse_ini_file($infoFile, true);
  53. if (isset($this->dictInfo['meta']['dictname'])) {
  54. // 是字典信息文件
  55. $this->info($this->dictInfo['meta']['dictname']);
  56. if (Str::isUuid($this->argument('uuid'))) {
  57. if ($this->argument('uuid') !== $this->dictInfo['meta']['uuid']) {
  58. continue;
  59. }
  60. }
  61. if (! Str::isUuid($this->dictInfo['meta']['uuid'])) {
  62. $this->error('not uuid');
  63. continue;
  64. }
  65. // 读取 description
  66. $desFile = $dir.'/description.md';
  67. if (file_exists($desFile)) {
  68. $description = file_get_contents($desFile);
  69. } else {
  70. $description = $this->dictInfo['meta']['description'];
  71. }
  72. $tableDict = DictInfo::firstOrNew([
  73. 'id' => $this->dictInfo['meta']['uuid'],
  74. ]);
  75. $tableDict->id = $this->dictInfo['meta']['uuid'];
  76. $tableDict->name = $this->dictInfo['meta']['dictname'];
  77. $tableDict->shortname = $this->dictInfo['meta']['shortname'];
  78. $tableDict->description = $description;
  79. $tableDict->src_lang = $this->dictInfo['meta']['src_lang'];
  80. $tableDict->dest_lang = $this->dictInfo['meta']['dest_lang'];
  81. $tableDict->rows = $this->dictInfo['meta']['rows'];
  82. $tableDict->owner_id = config('mint.admin.root_uuid');
  83. $tableDict->meta = json_encode($this->dictInfo['meta']);
  84. $tableDict->save();
  85. if ($this->option('part')) {
  86. $this->info(' dict id = '.$this->dictInfo['meta']['uuid']);
  87. } else {
  88. $del = UserDict::where('dict_id', $this->dictInfo['meta']['uuid'])->delete();
  89. $this->info("delete {$del} rows dict id = ".$this->dictInfo['meta']['uuid']);
  90. }
  91. /**
  92. * 允许一个字典拆成若干个小文件
  93. * 文件名 为 ***.csv , ***-1.csv , ***-2.csv
  94. */
  95. $filename = $dir.'/'.pathinfo($infoFile, PATHINFO_FILENAME);
  96. $csvFile = $filename.'.csv';
  97. $count = 0;
  98. $bar = $this->output->createProgressBar($this->dictInfo['meta']['rows']);
  99. while (file_exists($csvFile)) {
  100. // code...
  101. $this->info("runing:{$csvFile}");
  102. $inputRow = 0;
  103. if (($fp = fopen($csvFile, 'r')) !== false) {
  104. $this->cols = [];
  105. while (($data = fgetcsv($fp, 0, ',')) !== false) {
  106. if ($inputRow == 0) {
  107. foreach ($data as $key => $colname) {
  108. // 列名列表
  109. $this->cols[$colname] = $key;
  110. }
  111. } else {
  112. if ($this->option('part')) {
  113. // 仅仅提取拆分零件
  114. $word = $this->get($data, 'word');
  115. $factor1 = $this->get($data, 'factors');
  116. $factor1 = \str_replace([' ', '(', ')', '=', '-', '$'], '+', $factor1);
  117. foreach (\explode('+', $factor1) as $part) {
  118. // code...
  119. if (empty($part)) {
  120. continue;
  121. }
  122. if (isset($newPart[$part])) {
  123. $newPart[$part][0]++;
  124. } else {
  125. $partExists = Cache::remember('dict/part/'.$part, config('cache.expire', 1000), function () use ($part) {
  126. return UserDict::where('word', $part)->exists();
  127. });
  128. if (! $partExists) {
  129. $count++;
  130. $newPart[$part] = [1, $word];
  131. $this->info("{$count}:{$part}-{$word}");
  132. }
  133. }
  134. }
  135. } else {
  136. $newDict = new UserDict;
  137. $newDict->id = app('snowflake')->id();
  138. $newDict->word = $data[$this->cols['word']];
  139. $newDict->type = $this->get($data, 'type');
  140. $newDict->grammar = $this->get($data, 'grammar');
  141. $newDict->parent = $this->get($data, 'parent');
  142. $newDict->mean = $this->get($data, 'mean');
  143. $newDict->note = $this->get($data, 'note');
  144. $newDict->factors = $this->get($data, 'factors');
  145. $newDict->factormean = $this->get($data, 'factormean');
  146. $newDict->status = $this->get($data, 'status');
  147. $newDict->language = $this->get($data, 'language');
  148. $newDict->confidence = $this->get($data, 'confidence');
  149. $newDict->source = $this->get($data, 'source');
  150. $newDict->create_time = (int) (microtime(true) * 1000);
  151. $newDict->creator_id = 0;
  152. $newDict->dict_id = $this->dictInfo['meta']['uuid'];
  153. $newDict->save();
  154. }
  155. $bar->advance();
  156. }
  157. $inputRow++;
  158. }
  159. }
  160. $count++;
  161. $csvFile = $filename."-{$count}.csv";
  162. }
  163. $bar->finish();
  164. Storage::disk('local')->put('tmp/pm-part.csv', 'part,count,word');
  165. if (isset($newPart)) {
  166. foreach ($newPart as $part => $info) {
  167. // 写入磁盘文件
  168. Storage::disk('local')->append('tmp/pm-part.csv', "{$part},{$info[0]},{$info[1]}");
  169. }
  170. }
  171. $this->info('done');
  172. }
  173. }
  174. }
  175. }
  176. // 子目录搜素完毕
  177. return;
  178. } else {
  179. // 获取子目录失败
  180. $this->error('scandir fail');
  181. return;
  182. }
  183. } else {
  184. $this->error("this is not dir input={$dir}");
  185. return;
  186. }
  187. }
  188. /**
  189. * 获取列的值
  190. */
  191. protected function get(array $data, string $colName, $default = '')
  192. {
  193. if (isset($this->cols[$colName])) {
  194. return $data[$this->cols[$colName]];
  195. } elseif (isset($this->dictInfo['cols'][$colName])) {
  196. return $this->dictInfo['cols'][$colName];
  197. } else {
  198. return $default;
  199. }
  200. }
  201. /**
  202. * Execute the console command.
  203. *
  204. * @return int
  205. */
  206. public function handle()
  207. {
  208. if (Tools::isStop()) {
  209. return 0;
  210. }
  211. $this->info('upgrade dict start');
  212. $this->scanDict(config('mint.path.dict_text'));
  213. $this->info('upgrade dict done');
  214. return 0;
  215. }
  216. }