Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8160c1a

Browse files
feat: #70 continue when break
1 parent 19f0d83 commit 8160c1a

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

‎app/Commands/WikiImportCommand.php

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use DOMDocument;
99
use Exception;
1010
use Illuminate\Contracts\Filesystem\FileNotFoundException;
11+
use Illuminate\Support\Facades\File;
1112
use Illuminate\Support\Str;
1213
use LaravelFans\Confluence\Facades\Confluence;
1314
use LaravelZero\Framework\Commands\Command;
@@ -20,6 +21,7 @@ class WikiImportCommand extends Command
2021
protected Disk $codingDisk;
2122
protected Wiki $codingWiki;
2223
protected array $errors = [];
24+
protected array $importedPages = [];
2325

2426
/**
2527
* The signature of the command.
@@ -37,6 +39,7 @@ class WikiImportCommand extends Command
3739
{--coding_team_domain= : CODING 团队域名,如 xxx.coding.net 即填写 xxx}
3840
{--coding_project_uri= : CODING 项目标识,如 xxx.coding.net/p/yyy 即填写 yyy}
3941
{--save-markdown : 本地保留生成的 Markdown 文件}
42+
{--continue : 断点续传}
4043
';
4144

4245
/**
@@ -194,6 +197,9 @@ private function handleConfluenceHtml(): int
194197

195198
private function uploadConfluencePages(string $htmlDir, array $tree, array $titles, int $parentId = 0): void
196199
{
200+
if ($this->option('continue') && file_exists($htmlDir . DIRECTORY_SEPARATOR . 'success.log')) {
201+
$this->importedPages = parse_ini_file($htmlDir . DIRECTORY_SEPARATOR . 'success.log');
202+
}
197203
foreach ($tree as $page => $subPages) {
198204
$title = $titles[$page];
199205
$wikiId = $this->uploadConfluencePage($htmlDir . DIRECTORY_SEPARATOR . $page, $title, $parentId);
@@ -207,6 +213,11 @@ private function uploadConfluencePages(string $htmlDir, array $tree, array $titl
207213

208214
private function uploadConfluencePage(string $filePath, string $title = '', int $parentId = 0): int
209215
{
216+
$page = basename($filePath);
217+
if ($this->option('continue') && isset($this->importedPages[$page])) {
218+
$this->warn('断点续传,跳过页面:' . $page);
219+
return $this->importedPages[$page];
220+
}
210221
try {
211222
$markdown = $this->confluence->htmlFile2Markdown($filePath);
212223
} catch (FileNotFoundException $e) {
@@ -223,7 +234,6 @@ private function uploadConfluencePage(string $filePath, string $title = '', int
223234
$this->info('标题:' . $title);
224235

225236
$htmlDir = dirname($filePath);
226-
$page = basename($filePath);
227237
$markdown = $this->dealAttachments($filePath, $markdown);
228238
$mdFilename = substr($page, 0, -5) . '.md';
229239
if ($this->option('save-markdown')) {
@@ -244,22 +254,20 @@ private function uploadConfluencePage(string $filePath, string $title = '', int
244254
$this->codingProjectUri,
245255
$result['JobId']
246256
);
247-
} catch (Exception $e) {
248-
$message = '错误:导入失败,跳过 ' . $title . '' . $page;
249-
$this->error($message);
250-
$this->errors[] = $message;
251-
return false;
252-
}
253-
if ($jobStatus['Status'] == 'success') {
257+
if ($jobStatus['Status'] != 'success') {
258+
throw new Exception('job status ' . $jobStatus['Status']);
259+
}
254260
$wikiId = intval($jobStatus['Iids'][0]);
255-
}
256-
if (empty($wikiId)) {
261+
} catch (Exception $e) {
257262
$message = '错误:导入失败,跳过 ' . $title . '' . $page;
258263
$this->error($message);
259264
$this->errors[] = $message;
260265
return false;
261266
}
262267
$this->codingWiki->updateTitle($this->codingToken, $this->codingProjectUri, $wikiId, $title);
268+
if ($this->option('continue')) {
269+
file_put_contents($htmlDir . DIRECTORY_SEPARATOR . 'success.log', "$page = $wikiId\n", FILE_APPEND);
270+
}
263271
return $wikiId;
264272
}
265273

‎tests/Feature/WikiImportCommandTest.php

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Coding\Disk;
66
use App\Coding\Wiki;
77
use Confluence\Content;
8+
use Illuminate\Support\Facades\File;
89
use LaravelFans\Confluence\Facades\Confluence;
910
use Mockery\MockInterface;
1011
use Tests\TestCase;
@@ -180,7 +181,8 @@ public function testHandleConfluenceHtmlSuccess()
180181
$this->instance(Disk::class, $mockDisk);
181182
$mockDisk->shouldReceive('uploadAttachments')->times(4)->andReturn([]);
182183

183-
$this->artisan('wiki:import', ['--save-markdown' => true])
184+
File::delete($this->dataDir . '/confluence/space1/success.log');
185+
$this->artisan('wiki:import', ['--save-markdown' => true, '--continue' => true])
184186
->expectsQuestion('数据来源?', 'Confluence')
185187
->expectsQuestion('数据类型?', 'HTML')
186188
->expectsQuestion('空间导出的 HTML zip 文件路径', $this->dataDir . 'confluence/space1/')
@@ -207,6 +209,11 @@ public function testHandleConfluenceHtmlSuccess()
207209
unlink($this->dataDir . '/confluence/space1/65591.md');
208210
unlink($this->dataDir . '/confluence/space1/attachment-demo_65615.md');
209211
unlink($this->dataDir . '/confluence/space1/text-demo_65601.md');
212+
$log = "image-demo_65619.html = 27\n"
213+
. "65591.html = 27\n"
214+
. "attachment-demo_65615.html = 27\n"
215+
. "text-demo_65601.html = 27\n";
216+
$this->assertEquals($log, file_get_contents($this->dataDir . '/confluence/space1/success.log'));
210217
}
211218

212219
public function testAskNothing()
@@ -299,4 +306,58 @@ public function testHandleConfluenceSingleHtmlSuccess()
299306
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
300307
->assertExitCode(0);
301308
}
309+
310+
public function testHandleConfluenceHtmlContinueSuccess()
311+
{
312+
$this->setConfig();
313+
314+
// 注意:不能使用 partialMock
315+
// https://laracasts.com/discuss/channels/testing/this-partialmock-doesnt-call-the-constructor
316+
$mock = \Mockery::mock(Wiki::class, [])->makePartial();
317+
$this->instance(Wiki::class, $mock);
318+
319+
$mock->shouldReceive('createWikiByUploadZip')->times(2)->andReturn(json_decode(
320+
file_get_contents($this->dataDir . 'coding/' . 'CreateWikiByZipResponse.json'),
321+
true
322+
)['Response']);
323+
$mock->shouldReceive('getImportJobStatus')->times(2)->andReturn(json_decode(
324+
file_get_contents($this->dataDir . 'coding/' . 'DescribeImportJobStatusResponse.json'),
325+
true
326+
)['Response']['Data']);
327+
$mock->shouldReceive('updateTitle')->times(2)->andReturn(true);
328+
329+
330+
$mockDisk = \Mockery::mock(Disk::class, [])->makePartial();
331+
$this->instance(Disk::class, $mockDisk);
332+
$mockDisk->shouldReceive('uploadAttachments')->times(2)->andReturn([]);
333+
334+
$log = "image-demo_65619.html = 27\n"
335+
. "65591.html = 27\n";
336+
file_put_contents($this->dataDir . '/confluence/space1/success.log', $log);
337+
$this->artisan('wiki:import', ['--continue' => true])
338+
->expectsQuestion('数据来源?', 'Confluence')
339+
->expectsQuestion('数据类型?', 'HTML')
340+
->expectsQuestion('空间导出的 HTML zip 文件路径', $this->dataDir . 'confluence/space1/')
341+
->expectsOutput('空间名称:空间 1')
342+
->expectsOutput('空间标识:space1')
343+
->expectsOutput('发现 3 个一级页面')
344+
->expectsOutput("开始导入 CODING:")
345+
->expectsOutput('页面不存在:' . $this->dataDir . 'confluence/space1/not-found.html')
346+
->expectsOutput('断点续传,跳过页面:image-demo_65619.html')
347+
->expectsOutput('断点续传,跳过页面:65591.html')
348+
->expectsOutput('发现 2 个子页面')
349+
->expectsOutput('标题:Attachment Demo')
350+
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
351+
->expectsOutput('标题:Text Demo')
352+
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
353+
->expectsOutput('报错信息汇总:')
354+
->expectsOutput('页面不存在:' . $this->dataDir . 'confluence/space1/not-found.html')
355+
->assertExitCode(1);
356+
$log = "image-demo_65619.html = 27\n"
357+
. "65591.html = 27\n"
358+
. "attachment-demo_65615.html = 27\n"
359+
. "text-demo_65601.html = 27\n";
360+
$this->assertEquals($log, file_get_contents($this->dataDir . '/confluence/space1/success.log'));
361+
unlink($this->dataDir . '/confluence/space1/success.log');
362+
}
302363
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /