Skip to content

Commit c994af0

Browse files
committed
feat: #30 command wiki attachments
1 parent 6fb667c commit c994af0

15 files changed

+365
-229
lines changed

app/Coding/Base.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?php
2+
3+
namespace App\Coding;
4+
5+
use GuzzleHttp\Client;
6+
use Illuminate\Support\Facades\File;
7+
use Illuminate\Support\Facades\Storage;
8+
use ZipArchive;
9+
10+
class Base
11+
{
12+
protected Client $client;
13+
protected ZipArchive $zipArchive;
14+
15+
public function __construct(Client $client = null, ZipArchive $zipArchive = null)
16+
{
17+
$this->client = $client ?? new Client();
18+
$this->zipArchive = $zipArchive ?? new ZipArchive();
19+
}
20+
21+
public function createUploadToken($token, $projectName, $fileName)
22+
{
23+
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
24+
'headers' => [
25+
'Accept' => 'application/json',
26+
'Authorization' => "token ${token}",
27+
'Content-Type' => 'application/json'
28+
],
29+
'json' => [
30+
'Action' => 'CreateUploadToken',
31+
'ProjectName' => $projectName,
32+
'FileName' => $fileName,
33+
],
34+
]);
35+
$uploadToken = json_decode($response->getBody(), true)['Response']['Token'];
36+
preg_match_all(
37+
'|https://([a-z0-9\-]+)-(\d+)\.cos\.([a-z0-9\-]+)\.myqcloud\.com|',
38+
$uploadToken['UploadLink'],
39+
$matches
40+
);
41+
$uploadToken['Bucket'] = $matches[1][0] . '-' . $matches[2][0];
42+
$uploadToken['AppId'] = $matches[2][0];
43+
$uploadToken['Region'] = $matches[3][0];
44+
return $uploadToken;
45+
}
46+
47+
public function upload(array $uploadToken, string $fileFullPath): bool
48+
{
49+
config(['filesystems.disks.cos.credentials.appId' => $uploadToken['AppId']]);
50+
config(['filesystems.disks.cos.credentials.secretId' => $uploadToken['SecretId']]);
51+
config(['filesystems.disks.cos.credentials.secretKey' => $uploadToken['SecretKey']]);
52+
config(['filesystems.disks.cos.credentials.token' => $uploadToken['UpToken']]);
53+
config(['filesystems.disks.cos.region' => $uploadToken['Region']]);
54+
config(['filesystems.disks.cos.bucket' => $uploadToken['Bucket']]);
55+
56+
$disk = Storage::build(config('filesystems.disks.cos'));
57+
return $disk->put($uploadToken['StorageKey'], File::get($fileFullPath));
58+
}
59+
}

app/Coding/Disk.php

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
namespace App\Coding;
4+
5+
class Disk extends Base
6+
{
7+
/**
8+
* 创建网盘目录,不可重名,如已存在,仍然正常返回 id
9+
*
10+
* @param string $token
11+
* @param string $projectName
12+
* @param string $folderName
13+
* @param int $parentId
14+
* @return int
15+
* @throws \GuzzleHttp\Exception\GuzzleException
16+
*/
17+
public function createFolder(string $token, string $projectName, string $folderName, int $parentId = 0): int
18+
{
19+
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
20+
'headers' => [
21+
'Accept' => 'application/json',
22+
'Authorization' => "token ${token}",
23+
'Content-Type' => 'application/json'
24+
],
25+
'json' => [
26+
'Action' => 'CreateFolder',
27+
'ProjectName' => $projectName,
28+
'FolderName' => $folderName,
29+
'ParentId' => $parentId,
30+
],
31+
]);
32+
$result = json_decode($response->getBody(), true);
33+
return $result['Response']['Data']['Id'];
34+
}
35+
36+
/**
37+
* @param string $token
38+
* @param string $projectName
39+
* @param array $data
40+
* @return int
41+
* @throws \GuzzleHttp\Exception\GuzzleException
42+
* @todo data 数组无法强类型校验内部字段,考虑用对象
43+
*/
44+
public function createFile(string $token, string $projectName, array $data): array
45+
{
46+
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
47+
'headers' => [
48+
'Accept' => 'application/json',
49+
'Authorization' => "token ${token}",
50+
'Content-Type' => 'application/json'
51+
],
52+
'json' => array_merge([
53+
'Action' => 'CreateFile',
54+
'ProjectName' => $projectName,
55+
], $data),
56+
]);
57+
$result = json_decode($response->getBody(), true);
58+
return $result['Response']['Data'];
59+
}
60+
61+
public function uploadAttachments(string $token, string $projectName, string $dataPath, array $attachments): array
62+
{
63+
if (empty($attachments)) {
64+
return [];
65+
}
66+
$data = [];
67+
// TODO hard code folder name
68+
$folderId = $this->createFolder($token, $projectName, 'wiki-attachments');
69+
foreach ($attachments as $path => $filename) {
70+
$uploadToken = $this->createUploadToken(
71+
$token,
72+
$projectName,
73+
$filename
74+
);
75+
$this->upload($uploadToken, $dataPath . $path);
76+
$result = $this->createFile($token, $projectName, [
77+
"OriginalFileName" => $filename,
78+
"MimeType" => mime_content_type($dataPath . $path),
79+
"FileSize" => filesize($dataPath . $path),
80+
"StorageKey" => $uploadToken['StorageKey'],
81+
"Time" => $uploadToken['Time'],
82+
"AuthToken" => $uploadToken['AuthToken'],
83+
"FolderId" => 24515861,
84+
'ParentIid' => $folderId,
85+
]);
86+
$data[$path] = $result;
87+
}
88+
return $data;
89+
}
90+
}

app/Coding.php renamed to app/Coding/Wiki.php

Lines changed: 16 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
<?php
22

3-
namespace App;
3+
namespace App\Coding;
44

55
use Exception;
6-
use GuzzleHttp\Client;
7-
use Illuminate\Support\Facades\File;
86
use Illuminate\Support\Facades\Log;
9-
use Illuminate\Support\Facades\Storage;
107
use Illuminate\Support\Str;
118
use ZipArchive;
129

13-
class Coding
10+
class Wiki extends Base
1411
{
15-
private Client $client;
16-
private ZipArchive $zipArchive;
17-
18-
public function __construct(Client $client = null, ZipArchive $zipArchive = null)
19-
{
20-
$this->client = $client ?? new Client();
21-
$this->zipArchive = $zipArchive ?? new ZipArchive();
22-
}
23-
2412
public function createWiki($token, $projectName, $data)
2513
{
2614
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
@@ -37,32 +25,6 @@ public function createWiki($token, $projectName, $data)
3725
return json_decode($response->getBody(), true)['Response']['Data'];
3826
}
3927

40-
public function createUploadToken($token, $projectName, $fileName)
41-
{
42-
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
43-
'headers' => [
44-
'Accept' => 'application/json',
45-
'Authorization' => "token ${token}",
46-
'Content-Type' => 'application/json'
47-
],
48-
'json' => [
49-
'Action' => 'CreateUploadToken',
50-
'ProjectName' => $projectName,
51-
'FileName' => $fileName,
52-
],
53-
]);
54-
$uploadToken = json_decode($response->getBody(), true)['Response']['Token'];
55-
preg_match_all(
56-
'|https://([a-z0-9\-]+)-(\d+)\.cos\.([a-z0-9\-]+)\.myqcloud\.com|',
57-
$uploadToken['UploadLink'],
58-
$matches
59-
);
60-
$uploadToken['Bucket'] = $matches[1][0] . '-' . $matches[2][0];
61-
$uploadToken['AppId'] = $matches[2][0];
62-
$uploadToken['Region'] = $matches[3][0];
63-
return $uploadToken;
64-
}
65-
6628
public function createMarkdownZip($markdown, $path, $markdownFilename): bool|string
6729
{
6830
$zipFileFullPath = sys_get_temp_dir() . '/' . $markdownFilename . '-' . Str::uuid() . '.zip';
@@ -84,19 +46,6 @@ public function createMarkdownZip($markdown, $path, $markdownFilename): bool|str
8446
return $zipFileFullPath;
8547
}
8648

87-
public function upload(array $uploadToken, string $fileFullPath): bool
88-
{
89-
config(['filesystems.disks.cos.credentials.appId' => $uploadToken['AppId']]);
90-
config(['filesystems.disks.cos.credentials.secretId' => $uploadToken['SecretId']]);
91-
config(['filesystems.disks.cos.credentials.secretKey' => $uploadToken['SecretKey']]);
92-
config(['filesystems.disks.cos.credentials.token' => $uploadToken['UpToken']]);
93-
config(['filesystems.disks.cos.region' => $uploadToken['Region']]);
94-
config(['filesystems.disks.cos.bucket' => $uploadToken['Bucket']]);
95-
96-
$disk = Storage::build(config('filesystems.disks.cos'));
97-
return $disk->put($uploadToken['StorageKey'], File::get($fileFullPath));
98-
}
99-
10049
public function createWikiByZip(string $token, string $projectName, array $uploadToken, array $data)
10150
{
10251
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
@@ -202,57 +151,20 @@ public function updateWikiTitle(string $token, string $projectName, int $id, str
202151
return $result['Response']['Data']['Title'] == $title;
203152
}
204153

205-
/**
206-
* 创建网盘目录,不可重名,如已存在,仍然正常返回 id
207-
*
208-
* @param string $token
209-
* @param string $projectName
210-
* @param string $folderName
211-
* @param int $parentId
212-
* @return int
213-
* @throws \GuzzleHttp\Exception\GuzzleException
214-
*/
215-
public function createFolder(string $token, string $projectName, string $folderName, int $parentId): int
154+
public function replaceAttachments(string $markdown, array $codingAttachments): string
216155
{
217-
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
218-
'headers' => [
219-
'Accept' => 'application/json',
220-
'Authorization' => "token ${token}",
221-
'Content-Type' => 'application/json'
222-
],
223-
'json' => [
224-
'Action' => 'CreateFolder',
225-
'ProjectName' => $projectName,
226-
'FolderName' => $folderName,
227-
'ParentId' => $parentId,
228-
],
229-
]);
230-
$result = json_decode($response->getBody(), true);
231-
return $result['Response']['Data']['Id'];
232-
}
233-
234-
/**
235-
* @param string $token
236-
* @param string $projectName
237-
* @param array $data
238-
* @return int
239-
* @throws \GuzzleHttp\Exception\GuzzleException
240-
* @todo data 数组无法强类型校验内部字段,考虑用对象
241-
*/
242-
public function createFile(string $token, string $projectName, array $data): array
243-
{
244-
$response = $this->client->request('POST', 'https://e.coding.net/open-api', [
245-
'headers' => [
246-
'Accept' => 'application/json',
247-
'Authorization' => "token ${token}",
248-
'Content-Type' => 'application/json'
249-
],
250-
'json' => array_merge([
251-
'Action' => 'CreateFile',
252-
'ProjectName' => $projectName,
253-
], $data),
254-
]);
255-
$result = json_decode($response->getBody(), true);
256-
return $result['Response']['Data'];
156+
if (empty($codingAttachments)) {
157+
return $markdown;
158+
}
159+
$markdown .= "\n\nAttachments\n---\n";
160+
foreach ($codingAttachments as $attachmentPath => $codingAttachment) {
161+
$markdown .= "\n- #${codingAttachment['ResourceCode']} ${codingAttachment['FileName']}";
162+
$markdown = preg_replace(
163+
"|\[.*\]\(${attachmentPath}\)|",
164+
" #${codingAttachment['ResourceCode']} `${codingAttachment['FileName']}`",
165+
$markdown
166+
);
167+
}
168+
return $markdown;
257169
}
258170
}

app/Commands/WikiImportCommand.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
namespace App\Commands;
44

55
use App\Coding;
6+
use App\Coding\Disk;
7+
use App\Coding\Wiki;
68
use Confluence\Content;
79
use DOMDocument;
10+
use Exception;
811
use Illuminate\Support\Str;
912
use LaravelFans\Confluence\Facades\Confluence;
1013
use LaravelZero\Framework\Commands\Command;
@@ -13,6 +16,8 @@ class WikiImportCommand extends Command
1316
{
1417
use WithCoding;
1518

19+
protected Disk $codingDisk;
20+
protected Wiki $codingWiki;
1621
/**
1722
* The signature of the command.
1823
*
@@ -44,9 +49,10 @@ class WikiImportCommand extends Command
4449
* Execute the console command.
4550
*
4651
*/
47-
public function handle(Coding $coding, \App\Confluence $confluence, DOMDocument $document): int
52+
public function handle(Disk $codingDisk, Wiki $codingWiki, \App\Confluence $confluence, DOMDocument $document): int
4853
{
49-
$this->coding = $coding;
54+
$this->codingDisk = $codingDisk;
55+
$this->codingWiki = $codingWiki;
5056
$this->confluence = $confluence;
5157
$this->document = $document;
5258
$this->setCodingApi();
@@ -84,7 +90,7 @@ public function handle(Coding $coding, \App\Confluence $confluence, DOMDocument
8490

8591
private function createWiki($data)
8692
{
87-
$result = $this->coding->createWiki($this->codingToken, $this->codingProjectUri, $data);
93+
$result = $this->codingWiki->createWiki($this->codingToken, $this->codingProjectUri, $data);
8894
$path = $result['Path'];
8995
$this->info("https://{$this->codingTeamDomain}.coding.net/p/{$this->codingProjectUri}/wiki/${path}");
9096
}
@@ -180,9 +186,17 @@ private function uploadConfluencePages(string $dataPath, array $tree, array $tit
180186
$title = $titles[$page];
181187
$this->info('标题:' . $title);
182188
$markdown = $this->confluence->htmlFile2Markdown($dataPath . $page);
189+
$attachments = $this->confluence->parseAttachments($dataPath . $page, $markdown);
190+
$codingAttachments = $this->codingDisk->uploadAttachments(
191+
$this->codingToken,
192+
$this->codingProjectUri,
193+
$dataPath,
194+
$attachments
195+
);
196+
$markdown = $this->codingWiki->replaceAttachments($markdown, $codingAttachments);
183197
$mdFilename = substr($page, 0, -5) . '.md';
184-
$zipFilePath = $this->coding->createMarkdownZip($markdown, $dataPath, $mdFilename);
185-
$result = $this->coding->createWikiByUploadZip(
198+
$zipFilePath = $this->codingWiki->createMarkdownZip($markdown, $dataPath, $mdFilename);
199+
$result = $this->codingWiki->createWikiByUploadZip(
186200
$this->codingToken,
187201
$this->codingProjectUri,
188202
$zipFilePath,
@@ -194,18 +208,23 @@ private function uploadConfluencePages(string $dataPath, array $tree, array $tit
194208
while (true) {
195209
// HACK 如果上传成功立即查询,会报错:invoke function
196210
sleep(1);
197-
$jobStatus = $this->coding->getImportJobStatus(
198-
$this->codingToken,
199-
$this->codingProjectUri,
200-
$result['JobId']
201-
);
211+
try {
212+
$jobStatus = $this->codingWiki->getImportJobStatus(
213+
$this->codingToken,
214+
$this->codingProjectUri,
215+
$result['JobId']
216+
);
217+
} catch (Exception $e) {
218+
$waitingTimes++;
219+
continue;
220+
}
202221
if (in_array($jobStatus['Status'], ['wait_process', 'processing']) && $waitingTimes < 10) {
203222
$waitingTimes++;
204223
continue;
205224
}
206225
if ($jobStatus['Status'] == 'success') {
207226
$wikiId = intval($jobStatus['Iids'][0]);
208-
$this->coding->updateWikiTitle($this->codingToken, $this->codingProjectUri, $wikiId, $title);
227+
$this->codingWiki->updateWikiTitle($this->codingToken, $this->codingProjectUri, $wikiId, $title);
209228
}
210229
break;
211230
}

0 commit comments

Comments
 (0)