Skip to content

Commit 3626a22

Browse files
committed
Merge branch 'development' of github.com:LM-Nishant/BookStack into LM-Nishant-development
2 parents d13abc7 + 64da80c commit 3626a22

File tree

5 files changed

+171
-3
lines changed

5 files changed

+171
-3
lines changed

app/Exports/Controllers/BookExportApiController.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use BookStack\Entities\Queries\BookQueries;
66
use BookStack\Exports\ExportFormatter;
7+
use BookStack\Exports\ZipExports\ZipExportBuilder;
78
use BookStack\Http\ApiController;
89
use Throwable;
910

@@ -63,4 +64,19 @@ public function exportMarkdown(int $id)
6364

6465
return $this->download()->directly($markdown, $book->slug . '.md');
6566
}
66-
}
67+
68+
69+
/**
70+
* Export a book to a contained ZIP export file.
71+
* @throws NotFoundException
72+
*/
73+
public function exportZip(int $id, ZipExportBuilder $builder)
74+
{
75+
$book = $this->queries->findVisibleByIdOrFail($id);
76+
$bookName= $book->getShortName();
77+
78+
$zip = $builder->buildForBook($book);
79+
80+
return $this->download()->streamedFileDirectly($zip, $bookName . '.zip', filesize($zip), true);
81+
}
82+
}

app/Exports/Controllers/ChapterExportApiController.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use BookStack\Entities\Queries\ChapterQueries;
66
use BookStack\Exports\ExportFormatter;
7+
use BookStack\Exports\ZipExports\ZipExportBuilder;
78
use BookStack\Http\ApiController;
89
use Throwable;
910

@@ -63,4 +64,13 @@ public function exportMarkdown(int $id)
6364

6465
return $this->download()->directly($markdown, $chapter->slug . '.md');
6566
}
66-
}
67+
68+
public function exportZip(int $id, ZipExportBuilder $builder)
69+
{
70+
$chapter = $this->queries->findVisibleByIdOrFail($id);
71+
$chapterName= $chapter->getShortName();
72+
$zip = $builder->buildForChapter($chapter);
73+
74+
return $this->download()->streamedFileDirectly($zip, $chapterName . '.zip', filesize($zip), true);
75+
}
76+
}
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+
}

app/Exports/Controllers/PageExportApiController.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use BookStack\Entities\Queries\PageQueries;
66
use BookStack\Exports\ExportFormatter;
7+
use BookStack\Exports\ZipExports\ZipExportBuilder;
78
use BookStack\Http\ApiController;
89
use Throwable;
910

@@ -63,4 +64,15 @@ public function exportMarkdown(int $id)
6364

6465
return $this->download()->directly($markdown, $page->slug . '.md');
6566
}
66-
}
67+
68+
69+
70+
public function exportZip(int $id, ZipExportBuilder $builder)
71+
{
72+
$page = $this->queries->findVisibleByIdOrFail($id);
73+
$pageSlug = $page->slug;
74+
$zip = $builder->buildForPage($page);
75+
76+
return $this->download()->streamedFileDirectly($zip, $pageSlug . '.zip', filesize($zip), true);
77+
}
78+
}

routes/api.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
Route::get('books/{id}/export/pdf', [ExportControllers\BookExportApiController::class, 'exportPdf']);
3838
Route::get('books/{id}/export/plaintext', [ExportControllers\BookExportApiController::class, 'exportPlainText']);
3939
Route::get('books/{id}/export/markdown', [ExportControllers\BookExportApiController::class, 'exportMarkdown']);
40+
Route::get('books/{id}/export/zip', [ExportControllers\BookExportApiController::class, 'exportZip']);
4041

4142
Route::get('chapters', [EntityControllers\ChapterApiController::class, 'list']);
4243
Route::post('chapters', [EntityControllers\ChapterApiController::class, 'create']);
@@ -47,6 +48,7 @@
4748
Route::get('chapters/{id}/export/pdf', [ExportControllers\ChapterExportApiController::class, 'exportPdf']);
4849
Route::get('chapters/{id}/export/plaintext', [ExportControllers\ChapterExportApiController::class, 'exportPlainText']);
4950
Route::get('chapters/{id}/export/markdown', [ExportControllers\ChapterExportApiController::class, 'exportMarkdown']);
51+
Route::get('chapters/{id}/export/zip', [ExportControllers\ChapterExportApiController::class, 'exportZip']);
5052

5153
Route::get('pages', [EntityControllers\PageApiController::class, 'list']);
5254
Route::post('pages', [EntityControllers\PageApiController::class, 'create']);
@@ -58,6 +60,7 @@
5860
Route::get('pages/{id}/export/pdf', [ExportControllers\PageExportApiController::class, 'exportPdf']);
5961
Route::get('pages/{id}/export/plaintext', [ExportControllers\PageExportApiController::class, 'exportPlainText']);
6062
Route::get('pages/{id}/export/markdown', [ExportControllers\PageExportApiController::class, 'exportMarkdown']);
63+
Route::get('pages/{id}/export/zip', [ExportControllers\PageExportApiController::class, 'exportZip']);
6164

6265
Route::get('image-gallery', [ImageGalleryApiController::class, 'list']);
6366
Route::post('image-gallery', [ImageGalleryApiController::class, 'create']);
@@ -95,3 +98,9 @@
9598
Route::get('audit-log', [AuditLogApiController::class, 'list']);
9699

97100
Route::get('system', [SystemApiController::class, 'read']);
101+
102+
Route::get('import', [ExportControllers\ImportApiController::class, 'list']);
103+
Route::post('import', [ExportControllers\ImportApiController::class, 'upload']);
104+
Route::get('import/{id}', [ExportControllers\ImportApiController::class, 'read']);
105+
Route::post('import/{id}/create', [ExportControllers\ImportApiController::class, 'create']);
106+
Route::delete('import/{id}', [ExportControllers\ImportApiController::class, 'destroy']);

0 commit comments

Comments
 (0)