]> BookStack Code Mirror - bookstack/commitdiff
Develop functionality to import ZIP files. Create an API controller and define a...
author[email protected] <redacted>
Fri, 25 Apr 2025 07:18:34 +0000 (12:48 +0530)
committer[email protected] <redacted>
Fri, 25 Apr 2025 07:18:34 +0000 (12:48 +0530)
app/Exports/Controllers/ImportApiController.php [new file with mode: 0644]
routes/api.php

diff --git a/app/Exports/Controllers/ImportApiController.php b/app/Exports/Controllers/ImportApiController.php
new file mode 100644 (file)
index 0000000..682d340
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+
+declare(strict_types=1);
+
+namespace BookStack\Exports\Controllers;
+
+use BookStack\Exceptions\ZipImportException;
+use BookStack\Exceptions\ZipValidationException;
+use BookStack\Exports\ImportRepo;
+use BookStack\Http\Controller;
+use BookStack\Uploads\AttachmentService;
+use Illuminate\Http\Request;
+use Illuminate\Http\JsonResponse;
+
+class ImportApiController extends Controller
+{
+    public function __construct(
+        protected ImportRepo $imports,
+    ) {
+        $this->middleware('can:content-import');
+    }
+
+    /**
+     * List existing imports visible to the user.
+     */
+    public function list(): JsonResponse
+    {
+        $imports = $this->imports->getVisibleImports();
+
+        return response()->json([
+            'status' => 'success',
+            'imports' => $imports,
+        ]);
+    }
+
+    /**
+     * Upload, validate and store an import file.
+     */
+    public function upload(Request $request): JsonResponse
+    {
+        $this->validate($request, [
+            'file' => ['required', ...AttachmentService::getFileValidationRules()]
+        ]);
+
+        $file = $request->file('file');
+
+        try {
+            $import = $this->imports->storeFromUpload($file);
+        } catch (ZipValidationException $exception) {
+            return response()->json([
+                'status' => 'error',
+                'message' => 'Validation failed',
+                'errors' => $exception->errors,
+            ], 422);
+        }
+
+        return response()->json([
+            'status' => 'success',
+            'import' => $import,
+        ], 201);
+    }
+
+    /**
+     * Show details of a pending import.
+     */
+    public function read(int $id): JsonResponse
+    {
+        $import = $this->imports->findVisible($id);
+
+        return response()->json([
+            'status' => 'success',
+            'import' => $import,
+            'data' => $import->decodeMetadata(),
+        ]);
+    }
+
+    /**
+     * Run the import process.
+     */
+    public function create(int $id, Request $request): JsonResponse
+    {
+        $import = $this->imports->findVisible($id);
+        $parent = null;
+
+        if ($import->type === 'page' || $import->type === 'chapter') {
+            $data = $this->validate($request, [
+                'parent' => ['required', 'string'],
+            ]);
+            $parent = $data['parent'];
+        }
+
+        try {
+            $entity = $this->imports->runImport($import, $parent);
+        } catch (ZipImportException $exception) {
+            return response()->json([
+                'status' => 'error',
+                'message' => 'Import failed',
+                'errors' => $exception->errors,
+            ], 500);
+        }
+
+        return response()->json([
+            'status' => 'success',
+            'entity' => $entity,
+        ]);
+    }
+
+    /**
+     * Delete a pending import.
+     */
+    public function delete(int $id): JsonResponse
+    {
+        $import = $this->imports->findVisible($id);
+        $this->imports->deleteImport($import);
+
+        return response()->json([
+            'status' => 'success',
+            'message' => 'Import deleted successfully',
+        ]);
+    }
+}
\ No newline at end of file
index 71036485597d20d41e8b500aeded1341496d983b..bd00ea4b09869ddcdf18250d1a4fc3687b784afa 100644 (file)
@@ -92,3 +92,9 @@ Route::get('content-permissions/{contentType}/{contentId}', [ContentPermissionAp
 Route::put('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'update']);
 
 Route::get('audit-log', [AuditLogApiController::class, 'list']);
 Route::put('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'update']);
 
 Route::get('audit-log', [AuditLogApiController::class, 'list']);
+
+Route::get('import', [ExportControllers\ImportApiController::class, 'list']);
+Route::post('import', [ExportControllers\ImportApiController::class, 'upload']);
+Route::get('import/{id}', [ExportControllers\ImportApiController::class, 'read']);
+Route::post('import/{id}/create', [ExportControllers\ImportApiController::class, 'create']);
+Route::delete('import/{id}', [ExportControllers\ImportApiController::class, 'destroy']);
\ No newline at end of file