Skip to content

Commit

Permalink
feat: #66 import single html
Browse files Browse the repository at this point in the history
  • Loading branch information
sinkcup committed Aug 14, 2021
1 parent 9c268e3 commit 77285a3
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 67 deletions.
9 changes: 5 additions & 4 deletions app/Coding/Disk.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function createFile(string $token, string $projectName, array $data): arr
return $result['Response']['Data'];
}

public function uploadAttachments(string $token, string $projectName, string $dataPath, array $attachments): array
public function uploadAttachments(string $token, string $projectName, string $dataDir, array $attachments): array
{
if (empty($attachments)) {
return [];
Expand All @@ -72,13 +72,14 @@ public function uploadAttachments(string $token, string $projectName, string $da
$projectName,
$filename
);
$filePath = $dataDir . DIRECTORY_SEPARATOR . $path;
$result = [];
try {
$this->upload($uploadToken, $dataPath . $path);
$this->upload($uploadToken, $filePath);
$result = $this->createFile($token, $projectName, [
"OriginalFileName" => $filename,
"MimeType" => mime_content_type($dataPath . $path),
"FileSize" => filesize($dataPath . $path),
"MimeType" => mime_content_type($filePath),
"FileSize" => filesize($filePath),
"StorageKey" => $uploadToken['StorageKey'],
"Time" => $uploadToken['Time'],
"AuthToken" => $uploadToken['AuthToken'],
Expand Down
125 changes: 72 additions & 53 deletions app/Commands/WikiImportCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,12 @@ private function handleConfluenceApi(): int

private function handleConfluenceHtml(): int
{
$htmlDir = $this->unzipConfluenceHtml();
$filePath = $htmlDir . 'index.html';
$path = $this->unzipConfluenceHtml();
if (str_ends_with($path, '.html')) {
return $this->uploadConfluencePage($path);
}
$htmlDir = $path;
$filePath = $htmlDir . DIRECTORY_SEPARATOR . 'index.html';
if (!file_exists($filePath)) {
$message = "文件不存在:$filePath";
$this->error($message);
Expand Down Expand Up @@ -188,55 +192,75 @@ private function handleConfluenceHtml(): int
return 0;
}

private function uploadConfluencePages(string $dataPath, array $tree, array $titles, int $parentId = 0): void
private function uploadConfluencePages(string $htmlDir, array $tree, array $titles, int $parentId = 0): void
{
foreach ($tree as $page => $subPages) {
$title = $titles[$page];
$this->info('标题:' . $title);
try {
$markdown = $this->confluence->htmlFile2Markdown($dataPath . $page);
} catch (FileNotFoundException $e) {
$this->error('页面不存在:' . $dataPath . $page);
continue;
$wikiId = $this->uploadConfluencePage($htmlDir . DIRECTORY_SEPARATOR . $page, $title, $parentId);
if ($wikiId && !empty($subPages)) {
$this->info('发现 ' . count($subPages) . ' 个子页面');
// TODO tests
$this->uploadConfluencePages($htmlDir, $subPages, $titles, $wikiId);
}
$mdFilename = $this->dealAttachments($dataPath, $page, $markdown);
$zipFilePath = $this->codingWiki->createMarkdownZip($markdown, $dataPath, $mdFilename, $title);
$result = $this->codingWiki->createWikiByUploadZip(
}
}

private function uploadConfluencePage(string $filePath, string $title = '', int $parentId = 0): int
{
try {
$markdown = $this->confluence->htmlFile2Markdown($filePath);
} catch (FileNotFoundException $e) {
$message = '页面不存在:' . $filePath;
$this->error($message);
$this->errors[] = $message;
return false;
}
libxml_use_internal_errors(true);
$this->document->loadHTMLFile($filePath);
if (empty($title)) {
$title = $this->document->getElementsByTagName('title')[0]->nodeValue;
}
$this->info('标题:' . $title);

$htmlDir = dirname($filePath);
$page = basename($filePath);
$markdown = $this->dealAttachments($filePath, $markdown);
$mdFilename = substr($page, 0, -5) . '.md';
if ($this->option('save-markdown')) {
file_put_contents($htmlDir . DIRECTORY_SEPARATOR . $mdFilename, $markdown . "\n");
}
$zipFilePath = $this->codingWiki->createMarkdownZip($markdown, $htmlDir, $mdFilename, $title);
$result = $this->codingWiki->createWikiByUploadZip(
$this->codingToken,
$this->codingProjectUri,
$zipFilePath,
$parentId,
);
$this->info('上传成功,正在处理,任务 ID:' . $result['JobId']);
$wikiId = null;
try {
$jobStatus = $this->codingWiki->getImportJobStatusWithRetry(
$this->codingToken,
$this->codingProjectUri,
$zipFilePath,
$parentId,
$result['JobId']
);
$this->info('上传成功,正在处理,任务 ID:' . $result['JobId']);
$wikiId = null;
try {
$jobStatus = $this->codingWiki->getImportJobStatusWithRetry(
$this->codingToken,
$this->codingProjectUri,
$result['JobId']
);
} catch (Exception $e) {
$message = '错误:导入失败,跳过 ' . $title . ' ' . $page;
$this->error($message);
$this->errors[] = $message;
continue;
}
if ($jobStatus['Status'] == 'success') {
$wikiId = intval($jobStatus['Iids'][0]);
}
if (empty($wikiId)) {
$message = '错误:导入失败,跳过 ' . $title . ' ' . $page;
$this->error($message);
$this->errors[] = $message;
continue;
}
$this->codingWiki->updateTitle($this->codingToken, $this->codingProjectUri, $wikiId, $title);
if (!empty($subPages)) {
$this->info('发现 ' . count($subPages) . ' 个子页面');
// TODO tests
$this->uploadConfluencePages($dataPath, $subPages, $titles, $wikiId);
}
} catch (Exception $e) {
$message = '错误:导入失败,跳过 ' . $title . ' ' . $page;
$this->error($message);
$this->errors[] = $message;
return false;
}
if ($jobStatus['Status'] == 'success') {
$wikiId = intval($jobStatus['Iids'][0]);
}
if (empty($wikiId)) {
$message = '错误:导入失败,跳过 ' . $title . ' ' . $page;
$this->error($message);
$this->errors[] = $message;
return false;
}
$this->codingWiki->updateTitle($this->codingToken, $this->codingProjectUri, $wikiId, $title);
return $wikiId;
}

private function unzipConfluenceHtml(): string
Expand All @@ -263,16 +287,16 @@ private function unzipConfluenceHtml(): string
$zip->close();
return $tmpDir . '/' . scandir($tmpDir, 1)[0] . '/';
}
return str_ends_with($dataPath, '/index.html') ? substr($dataPath, 0, -10) : Str::finish($dataPath, '/');
return rtrim($dataPath, '/');
}

private function dealAttachments(string $dataPath, string $page, string $markdown): string
private function dealAttachments(string $filePath, string $markdown): string
{
$attachments = $this->confluence->parseAttachments($dataPath . $page, $markdown);
$attachments = $this->confluence->parseAttachments($filePath, $markdown);
$codingAttachments = $this->codingDisk->uploadAttachments(
$this->codingToken,
$this->codingProjectUri,
$dataPath,
dirname($filePath),
$attachments
);
foreach ($codingAttachments as $attachmentPath => $codingAttachment) {
Expand All @@ -282,11 +306,6 @@ private function dealAttachments(string $dataPath, string $page, string $markdow
$this->errors[] = $message;
}
}
$markdown = $this->codingWiki->replaceAttachments($markdown, $codingAttachments);
$mdFilename = substr($page, 0, -5) . '.md';
if ($this->option('save-markdown')) {
file_put_contents($dataPath . $mdFilename, $markdown . "\n");
}
return $mdFilename;
return $this->codingWiki->replaceAttachments($markdown, $codingAttachments);
}
}
2 changes: 1 addition & 1 deletion app/Commands/WikiUploadCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class WikiUploadCommand extends Command
*
* @var string
*/
protected $description = '上传 Zip 导入 Wiki';
protected $description = '上传 Markdown 和图片的 Zip 导入 Wiki';

/**
* Execute the console command.
Expand Down
48 changes: 39 additions & 9 deletions tests/Feature/WikiImportCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public function testHandleConfluenceHtmlFileNotExist()
->expectsQuestion('数据来源?', 'Confluence')
->expectsQuestion('数据类型?', 'HTML')
->expectsQuestion('空间导出的 HTML zip 文件路径', '/dev/null/index.html')
->expectsOutput('文件不存在:/dev/null/index.html')
->expectsOutput('页面不存在:/dev/null/index.html')
->assertExitCode(1);
}

Expand Down Expand Up @@ -188,7 +188,6 @@ public function testHandleConfluenceHtmlSuccess()
->expectsOutput('空间标识:space1')
->expectsOutput('发现 3 个一级页面')
->expectsOutput("开始导入 CODING:")
->expectsOutput('标题:Not Found')
->expectsOutput('页面不存在:' . $this->dataDir . 'confluence/space1/not-found.html')
->expectsOutput('标题:Image Demo')
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
Expand All @@ -199,13 +198,15 @@ public function testHandleConfluenceHtmlSuccess()
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
->expectsOutput('标题:Text Demo')
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
->assertExitCode(0);
$this->assertFileExists($this->dataDir . 'confluence/space1/65591.md');
$this->assertFileExists($this->dataDir . 'confluence/space1/attachment-demo_65615.md');
$this->assertFileExists($this->dataDir . 'confluence/space1/text-demo_65601.md');
unlink($this->dataDir . 'confluence/space1/65591.md');
unlink($this->dataDir . 'confluence/space1/attachment-demo_65615.md');
unlink($this->dataDir . 'confluence/space1/text-demo_65601.md');
->expectsOutput('报错信息汇总:')
->expectsOutput('页面不存在:' . $this->dataDir . 'confluence/space1/not-found.html')
->assertExitCode(1);
$this->assertFileExists($this->dataDir . '/confluence/space1/65591.md');
$this->assertFileExists($this->dataDir . '/confluence/space1/attachment-demo_65615.md');
$this->assertFileExists($this->dataDir . '/confluence/space1/text-demo_65601.md');
unlink($this->dataDir . '/confluence/space1/65591.md');
unlink($this->dataDir . '/confluence/space1/attachment-demo_65615.md');
unlink($this->dataDir . '/confluence/space1/text-demo_65601.md');
}

public function testAskNothing()
Expand Down Expand Up @@ -269,4 +270,33 @@ public function testHandleConfluenceHtmlZipSuccess()
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
->assertExitCode(0);
}

public function testHandleConfluenceSingleHtmlSuccess()
{
$this->setConfig();

// 注意:不能使用 partialMock
// https://laracasts.com/discuss/channels/testing/this-partialmock-doesnt-call-the-constructor
$mock = \Mockery::mock(Wiki::class, [])->makePartial();
$this->instance(Wiki::class, $mock);

$mock->shouldReceive('createWikiByUploadZip')->times(1)->andReturn(json_decode(
file_get_contents($this->dataDir . 'coding/' . 'CreateWikiByZipResponse.json'),
true
)['Response']);
$mock->shouldReceive('getImportJobStatus')->times(1)->andReturn(json_decode(
file_get_contents($this->dataDir . 'coding/' . 'DescribeImportJobStatusResponse.json'),
true
)['Response']['Data']);
$mock->shouldReceive('updateTitle')->times(1)->andReturn(true);


$this->artisan('wiki:import')
->expectsQuestion('数据来源?', 'Confluence')
->expectsQuestion('数据类型?', 'HTML')
->expectsQuestion('空间导出的 HTML zip 文件路径', $this->dataDir . 'confluence/space1/image-demo_65619.html')
->expectsOutput('标题:空间 1 : Image Demo')
->expectsOutput('上传成功,正在处理,任务 ID:a12353fa-f45b-4af2-83db-666bf9f66615')
->assertExitCode(0);
}
}

0 comments on commit 77285a3

Please sign in to comment.