ImportArticleMap.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. <?php
  2. namespace App\Console\Commands;
  3. use App\Http\Api\StudioApi;
  4. use App\Models\Article;
  5. use App\Models\Collection;
  6. use Illuminate\Console\Command;
  7. use Illuminate\Support\Facades\Http;
  8. use Illuminate\Support\Facades\Log;
  9. class ImportArticleMap extends Command
  10. {
  11. /**
  12. * The name and signature of the console command.
  13. * php artisan import:article.map visuddhinanda --studio=visuddhinanda --size=30000 --anthology=4c6b661b-fd68-44c5-8918-2e327c870b9a --token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJuYmYiOjE2OTc3Mjg2ODUsImV4cCI6MTcyOTI2NDY4NSwidWlkIjoiYmE1NDYzZjMtNzJkMS00NDEwLTg1OGUtZWFkZDEwODg0NzEzIiwiaWQiOjR9.fiXhnY2LczZ9kKVHV0FfD3AJPZt-uqM5wrDe4EhToVexdd007ebPFYssZefmchfL0mx9nF0rgHSqjNhx4P0yDA
  14. *
  15. * @var string
  16. */
  17. protected $signature = 'import:article.map {src_studio} {--token=} {--studio=} {--anthology=} {--size=}';
  18. /**
  19. * The console command description.
  20. *
  21. * @var string
  22. */
  23. protected $description = '重置缅文tipitaka sarupa文章目录';
  24. /**
  25. * Create a new command instance.
  26. *
  27. * @return void
  28. */
  29. public function __construct()
  30. {
  31. parent::__construct();
  32. }
  33. /**
  34. * Execute the console command.
  35. *
  36. * @return int
  37. */
  38. public function handle()
  39. {
  40. $token = $this->option('token');
  41. $studioName = $this->option('studio');
  42. $anthologyId = $this->option('anthology');
  43. $srcStudio = $this->argument('src_studio');
  44. if (! $this->confirm('Do you wish to continue?')) {
  45. return 0;
  46. }
  47. $studioId = StudioApi::getIdByName($studioName);
  48. if (! $studioId) {
  49. $this->error("can not found studio name {$studioName}");
  50. return 0;
  51. }
  52. $srcStudioId = StudioApi::getIdByName($srcStudio);
  53. if (! $srcStudioId) {
  54. $this->error("can not found src studio name {$srcStudio}");
  55. return 0;
  56. }
  57. // 先获取文章列表,建立全部目录
  58. $url = config('app.url').'/api/v2/article-map';
  59. $this->info('打开csv文件并读取数据');
  60. $head = [];
  61. $strFileName = __DIR__.'/tipitaka-sarupa.csv';
  62. if (! file_exists($strFileName)) {
  63. $this->error($strFileName.'文件不存在');
  64. return 1;
  65. }
  66. if (($fp = fopen($strFileName, 'r')) === false) {
  67. $this->error("can not open csv {$strFileName}");
  68. return 0;
  69. }
  70. // 查询文集语言
  71. $srcAnthology = Collection::where('uid', $anthologyId)->first();
  72. if (! $srcAnthology) {
  73. $this->error('文集不存在 anthologyId='.$anthologyId);
  74. return 0;
  75. }
  76. $lang = $srcAnthology->lang;
  77. if (empty($lang)) {
  78. $this->error('文集语言不能为空 anthologyId='.$anthologyId);
  79. return 0;
  80. }
  81. $inputRow = 0;
  82. $currSize = 0;
  83. $currBlock = 1;
  84. $currDir = '';
  85. $success = 0;
  86. $fail = 0;
  87. $articleMap = [];
  88. while (($data = fgetcsv($fp, 0, ',')) !== false) {
  89. if ($inputRow > 0) {
  90. $id = $data[0];
  91. $dir = $data[1];
  92. $title = $data[2];
  93. $realTitle = "[{$id}]{$title}";
  94. $realTitle = mb_substr($realTitle, 0, 128, 'UTF-8');
  95. $reference = $data[5];
  96. $percent = (int) ($inputRow * 100 / 6984);
  97. $this->info("[{$percent}%] doing ".$realTitle);
  98. if ($this->option('size')) {
  99. $currDir = $srcAnthology->title.'-'.$currBlock;
  100. if ($currSize > $this->option('size')) {
  101. $currBlock++;
  102. $currSize = 0;
  103. }
  104. } else {
  105. $currDir = $dir;
  106. }
  107. // 查找目录文章是否存在
  108. $dirArticle = Article::where('owner', $studioId)
  109. ->where('title', $currDir)
  110. ->first();
  111. if ($dirArticle) {
  112. $dirId = $dirArticle->uid;
  113. } else {
  114. $this->info('不存在目录'.$currDir.'新建');
  115. $url = config('app.url').'/api/v2/article';
  116. sleep(2);
  117. $response = Http::withToken($token)->post($url,
  118. [
  119. 'title' => $currDir,
  120. 'lang' => $lang,
  121. 'studio' => $studioName,
  122. 'anthologyId' => $anthologyId,
  123. ]);
  124. if ($response->ok()) {
  125. $this->info('dir create ok title='.$currDir);
  126. $dirId = $response->json('data.uid');
  127. } else {
  128. $this->error('create dir fail.'.$currDir);
  129. Log::error('create dir fail title='.$currDir);
  130. $fail++;
  131. continue;
  132. }
  133. }
  134. // 创建目录结束
  135. if (! isset($articleMap[$dirId])) {
  136. $articleMap[$dirId] = ['name' => $currDir, 'children' => []];
  137. }
  138. // 查找文章
  139. $article = Article::where('owner', $srcStudioId)
  140. ->where('title', $realTitle)
  141. ->first();
  142. if (! $article) {
  143. $this->error('文章没找到.'.$realTitle);
  144. Log::error('文章没找到 title='.$realTitle);
  145. $fail++;
  146. continue;
  147. }
  148. $articleMap[$dirId]['children'][] = [
  149. 'id' => $article->uid,
  150. 'title' => $article->title,
  151. ];
  152. if ($this->option('size')) {
  153. $currSize += mb_strlen($title, 'UTF-8') +
  154. mb_strlen($data[4], 'UTF-8') +
  155. mb_strlen($reference, 'UTF-8');
  156. }
  157. $success++;
  158. }
  159. $inputRow++;
  160. }
  161. $this->info('找到文章='.$success);
  162. $this->info('目录='.count($articleMap));
  163. $this->info('正在准备map数据');
  164. $data = [];
  165. foreach ($articleMap as $dirId => $dir) {
  166. $data[] = [
  167. 'article_id' => $dirId,
  168. 'level' => 1,
  169. 'title' => $dir['name'],
  170. 'children' => count($dir['children']),
  171. 'deleted_at' => null,
  172. ];
  173. foreach ($dir['children'] as $key => $child) {
  174. $data[] = [
  175. 'article_id' => $child['id'],
  176. 'level' => 2,
  177. 'title' => $child['title'],
  178. 'children' => 0,
  179. 'deleted_at' => null,
  180. ];
  181. }
  182. }
  183. $this->info('map data='.count($data));
  184. // 目录写入db
  185. $url = config('app.url').'/api/v2/article-map/'.$anthologyId;
  186. $response = Http::withToken($token)->put($url,
  187. [
  188. 'data' => $data,
  189. 'operation' => 'anthology',
  190. ]);
  191. if ($response->ok()) {
  192. $this->info('map update ok ');
  193. } else {
  194. $this->error('map update fail.');
  195. Log::error('map update fail ');
  196. }
  197. return 0;
  198. }
  199. }