Skip to content

Commit 5fa728f

Browse files
committed
Develop functionality to import ZIP files. Create an API controller and define a route entry for handling the import process. Implement logic to read the list of files within the ZIP, process the directory structure, and automatically create associated pages, chapters, and books based on the ZIP file's contents.
1 parent c61ce8d commit 5fa728f

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BookStack\Exports\Controllers;
6+
7+
use BookStack\Exceptions\ZipImportException;
8+
use BookStack\Exceptions\ZipValidationException;
9+
use BookStack\Exports\ImportRepo;
10+
use BookStack\Http\Controller;
11+
use BookStack\Uploads\AttachmentService;
12+
use Illuminate\Http\Request;
13+
use Illuminate\Http\JsonResponse;
14+
15+
class ImportApiController extends Controller
16+
{
17+
public function __construct(
18+
protected ImportRepo $imports,
19+
) {
20+
$this->middleware('can:content-import');
21+
}
22+
23+
/**
24+
* List existing imports visible to the user.
25+
*/
26+
public function list(): JsonResponse
27+
{
28+
$imports = $this->imports->getVisibleImports();
29+
30+
return response()->json([
31+
'status' => 'success',
32+
'imports' => $imports,
33+
]);
34+
}
35+
36+
/**
37+
* Upload, validate and store an import file.
38+
*/
39+
public function upload(Request $request): JsonResponse
40+
{
41+
$this->validate($request, [
42+
'file' => ['required', ...AttachmentService::getFileValidationRules()]
43+
]);
44+
45+
$file = $request->file('file');
46+
47+
try {
48+
$import = $this->imports->storeFromUpload($file);
49+
} catch (ZipValidationException $exception) {
50+
return response()->json([
51+
'status' => 'error',
52+
'message' => 'Validation failed',
53+
'errors' => $exception->errors,
54+
], 422);
55+
}
56+
57+
return response()->json([
58+
'status' => 'success',
59+
'import' => $import,
60+
], 201);
61+
}
62+
63+
/**
64+
* Show details of a pending import.
65+
*/
66+
public function read(int $id): JsonResponse
67+
{
68+
$import = $this->imports->findVisible($id);
69+
70+
return response()->json([
71+
'status' => 'success',
72+
'import' => $import,
73+
'data' => $import->decodeMetadata(),
74+
]);
75+
}
76+
77+
/**
78+
* Run the import process.
79+
*/
80+
public function create(int $id, Request $request): JsonResponse
81+
{
82+
$import = $this->imports->findVisible($id);
83+
$parent = null;
84+
85+
if ($import->type === 'page' || $import->type === 'chapter') {
86+
$data = $this->validate($request, [
87+
'parent' => ['required', 'string'],
88+
]);
89+
$parent = $data['parent'];
90+
}
91+
92+
try {
93+
$entity = $this->imports->runImport($import, $parent);
94+
} catch (ZipImportException $exception) {
95+
return response()->json([
96+
'status' => 'error',
97+
'message' => 'Import failed',
98+
'errors' => $exception->errors,
99+
], 500);
100+
}
101+
102+
return response()->json([
103+
'status' => 'success',
104+
'entity' => $entity,
105+
]);
106+
}
107+
108+
/**
109+
* Delete a pending import.
110+
*/
111+
public function delete(int $id): JsonResponse
112+
{
113+
$import = $this->imports->findVisible($id);
114+
$this->imports->deleteImport($import);
115+
116+
return response()->json([
117+
'status' => 'success',
118+
'message' => 'Import deleted successfully',
119+
]);
120+
}
121+
}

routes/api.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,9 @@
9292
Route::put('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'update']);
9393

9494
Route::get('audit-log', [AuditLogApiController::class, 'list']);
95+
96+
Route::get('import', [ExportControllers\ImportApiController::class, 'list']);
97+
Route::post('import', [ExportControllers\ImportApiController::class, 'upload']);
98+
Route::get('import/{id}', [ExportControllers\ImportApiController::class, 'read']);
99+
Route::post('import/{id}/create', [ExportControllers\ImportApiController::class, 'create']);
100+
Route::delete('import/{id}', [ExportControllers\ImportApiController::class, 'destroy']);

0 commit comments

Comments
 (0)