mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-29 23:22:34 +01:00
ZIP Exports: Finished up format doc, move files, started builder
Moved all existing export related app files into their new own dir.
This commit is contained in:
parent
42bd07d733
commit
42b9700673
7
app/Exceptions/ZipExportException.php
Normal file
7
app/Exceptions/ZipExportException.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Exceptions;
|
||||
|
||||
class ZipExportException extends \Exception
|
||||
{
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Controllers;
|
||||
namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\BookQueries;
|
||||
use BookStack\Entities\Tools\ExportFormatter;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Http\ApiController;
|
||||
use Throwable;
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Controllers;
|
||||
namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\BookQueries;
|
||||
use BookStack\Entities\Tools\ExportFormatter;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Http\Controller;
|
||||
use Throwable;
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Controllers;
|
||||
namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\ChapterQueries;
|
||||
use BookStack\Entities\Tools\ExportFormatter;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Http\ApiController;
|
||||
use Throwable;
|
||||
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Controllers;
|
||||
namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\ChapterQueries;
|
||||
use BookStack\Entities\Tools\ExportFormatter;
|
||||
use BookStack\Exceptions\NotFoundException;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Http\Controller;
|
||||
use Throwable;
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Controllers;
|
||||
namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\PageQueries;
|
||||
use BookStack\Entities\Tools\ExportFormatter;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Http\ApiController;
|
||||
use Throwable;
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Controllers;
|
||||
namespace BookStack\Exports\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\PageQueries;
|
||||
use BookStack\Entities\Tools\ExportFormatter;
|
||||
use BookStack\Entities\Tools\PageContent;
|
||||
use BookStack\Exceptions\NotFoundException;
|
||||
use BookStack\Exports\ExportFormatter;
|
||||
use BookStack\Http\Controller;
|
||||
use Throwable;
|
||||
|
@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Tools;
|
||||
namespace BookStack\Exports;
|
||||
|
||||
use BookStack\Entities\Models\Book;
|
||||
use BookStack\Entities\Models\Chapter;
|
||||
use BookStack\Entities\Models\Page;
|
||||
use BookStack\Entities\Tools\BookContents;
|
||||
use BookStack\Entities\Tools\Markdown\HtmlToMarkdown;
|
||||
use BookStack\Entities\Tools\PageContent;
|
||||
use BookStack\Uploads\ImageService;
|
||||
use BookStack\Util\CspService;
|
||||
use BookStack\Util\HtmlDocument;
|
@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Entities\Tools;
|
||||
namespace BookStack\Exports;
|
||||
|
||||
use BookStack\Exceptions\PdfExportException;
|
||||
use Knp\Snappy\Pdf as SnappyPdf;
|
||||
use Dompdf\Dompdf;
|
||||
use Knp\Snappy\Pdf as SnappyPdf;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
48
app/Exports/ZipExportBuilder.php
Normal file
48
app/Exports/ZipExportBuilder.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Exports;
|
||||
|
||||
use BookStack\Entities\Models\Page;
|
||||
use BookStack\Exceptions\ZipExportException;
|
||||
use ZipArchive;
|
||||
|
||||
class ZipExportBuilder
|
||||
{
|
||||
protected array $data = [];
|
||||
|
||||
/**
|
||||
* @throws ZipExportException
|
||||
*/
|
||||
public function buildForPage(Page $page): string
|
||||
{
|
||||
$this->data['page'] = [
|
||||
'id' => $page->id,
|
||||
];
|
||||
|
||||
return $this->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ZipExportException
|
||||
*/
|
||||
protected function build(): string
|
||||
{
|
||||
$this->data['exported_at'] = date(DATE_ATOM);
|
||||
$this->data['instance'] = [
|
||||
'version' => trim(file_get_contents(base_path('version'))),
|
||||
'id_ciphertext' => encrypt('bookstack'),
|
||||
];
|
||||
|
||||
$zipFile = tempnam(sys_get_temp_dir(), 'bszip-');
|
||||
$zip = new ZipArchive();
|
||||
$opened = $zip->open($zipFile, ZipArchive::CREATE);
|
||||
if ($opened !== true) {
|
||||
throw new ZipExportException('Failed to create zip file for export.');
|
||||
}
|
||||
|
||||
$zip->addFromString('data.json', json_encode($this->data));
|
||||
$zip->addEmptyDir('files');
|
||||
|
||||
return $zipFile;
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-zip": "*",
|
||||
"bacon/bacon-qr-code": "^3.0",
|
||||
"doctrine/dbal": "^3.5",
|
||||
"dompdf/dompdf": "^3.0",
|
||||
|
@ -39,18 +39,24 @@ Some properties in the export data JSON are indicated as `String reference`, and
|
||||
}
|
||||
```
|
||||
|
||||
TODO - Jotting out idea below.
|
||||
Would need to validate image/attachment paths against image/attachments listed across all pages in export.
|
||||
Probably good to ensure filenames are ascii-alpha-num.
|
||||
`[[bsexport:image:an-image-path.png]]`
|
||||
`[[bsexport:attachment:an-image-path.png]]`
|
||||
`[[bsexport:page:1]]`
|
||||
`[[bsexport:chapter:2]]`
|
||||
`[[bsexport:book:3]]`
|
||||
Within HTML and markdown content, you may require references across to other items within the export content.
|
||||
This can be done using the following format:
|
||||
|
||||
TODO - Define how we reference across content:
|
||||
TODO - References from in-content to file URLs
|
||||
TODO - References from in-content to in-export content (page cross links within same export).
|
||||
```
|
||||
[[bsexport:<object>:<reference>]]
|
||||
```
|
||||
|
||||
Images and attachments are referenced via their file name within the `files/` directory.
|
||||
Otherwise, other content types are referenced by `id`.
|
||||
Here's an example of each type of such reference that could be used:
|
||||
|
||||
```
|
||||
[[bsexport:image:an-image-path.png]]
|
||||
[[bsexport:attachment:an-image-path.png]]
|
||||
[[bsexport:page:40]]
|
||||
[[bsexport:chapter:2]]
|
||||
[[bsexport:book:8]]
|
||||
```
|
||||
|
||||
## Export Data - `data.json`
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
use BookStack\Activity\Controllers\AuditLogApiController;
|
||||
use BookStack\Api\ApiDocsController;
|
||||
use BookStack\Entities\Controllers as EntityControllers;
|
||||
use BookStack\Exports\Controllers as ExportControllers;
|
||||
use BookStack\Permissions\ContentPermissionApiController;
|
||||
use BookStack\Search\SearchApiController;
|
||||
use BookStack\Uploads\Controllers\AttachmentApiController;
|
||||
@ -31,21 +32,20 @@ Route::get('books/{id}', [EntityControllers\BookApiController::class, 'read']);
|
||||
Route::put('books/{id}', [EntityControllers\BookApiController::class, 'update']);
|
||||
Route::delete('books/{id}', [EntityControllers\BookApiController::class, 'delete']);
|
||||
|
||||
Route::get('books/{id}/export/html', [EntityControllers\BookExportApiController::class, 'exportHtml']);
|
||||
Route::get('books/{id}/export/pdf', [EntityControllers\BookExportApiController::class, 'exportPdf']);
|
||||
Route::get('books/{id}/export/plaintext', [EntityControllers\BookExportApiController::class, 'exportPlainText']);
|
||||
Route::get('books/{id}/export/markdown', [EntityControllers\BookExportApiController::class, 'exportMarkdown']);
|
||||
Route::get('books/{id}/export/html', [ExportControllers\BookExportApiController::class, 'exportHtml']);
|
||||
Route::get('books/{id}/export/pdf', [ExportControllers\BookExportApiController::class, 'exportPdf']);
|
||||
Route::get('books/{id}/export/plaintext', [ExportControllers\BookExportApiController::class, 'exportPlainText']);
|
||||
Route::get('books/{id}/export/markdown', [ExportControllers\BookExportApiController::class, 'exportMarkdown']);
|
||||
|
||||
Route::get('chapters', [EntityControllers\ChapterApiController::class, 'list']);
|
||||
Route::post('chapters', [EntityControllers\ChapterApiController::class, 'create']);
|
||||
Route::get('chapters/{id}', [EntityControllers\ChapterApiController::class, 'read']);
|
||||
Route::put('chapters/{id}', [EntityControllers\ChapterApiController::class, 'update']);
|
||||
Route::delete('chapters/{id}', [EntityControllers\ChapterApiController::class, 'delete']);
|
||||
|
||||
Route::get('chapters/{id}/export/html', [EntityControllers\ChapterExportApiController::class, 'exportHtml']);
|
||||
Route::get('chapters/{id}/export/pdf', [EntityControllers\ChapterExportApiController::class, 'exportPdf']);
|
||||
Route::get('chapters/{id}/export/plaintext', [EntityControllers\ChapterExportApiController::class, 'exportPlainText']);
|
||||
Route::get('chapters/{id}/export/markdown', [EntityControllers\ChapterExportApiController::class, 'exportMarkdown']);
|
||||
Route::get('chapters/{id}/export/html', [ExportControllers\ChapterExportApiController::class, 'exportHtml']);
|
||||
Route::get('chapters/{id}/export/pdf', [ExportControllers\ChapterExportApiController::class, 'exportPdf']);
|
||||
Route::get('chapters/{id}/export/plaintext', [ExportControllers\ChapterExportApiController::class, 'exportPlainText']);
|
||||
Route::get('chapters/{id}/export/markdown', [ExportControllers\ChapterExportApiController::class, 'exportMarkdown']);
|
||||
|
||||
Route::get('pages', [EntityControllers\PageApiController::class, 'list']);
|
||||
Route::post('pages', [EntityControllers\PageApiController::class, 'create']);
|
||||
@ -53,10 +53,10 @@ Route::get('pages/{id}', [EntityControllers\PageApiController::class, 'read']);
|
||||
Route::put('pages/{id}', [EntityControllers\PageApiController::class, 'update']);
|
||||
Route::delete('pages/{id}', [EntityControllers\PageApiController::class, 'delete']);
|
||||
|
||||
Route::get('pages/{id}/export/html', [EntityControllers\PageExportApiController::class, 'exportHtml']);
|
||||
Route::get('pages/{id}/export/pdf', [EntityControllers\PageExportApiController::class, 'exportPdf']);
|
||||
Route::get('pages/{id}/export/plaintext', [EntityControllers\PageExportApiController::class, 'exportPlainText']);
|
||||
Route::get('pages/{id}/export/markdown', [EntityControllers\PageExportApiController::class, 'exportMarkdown']);
|
||||
Route::get('pages/{id}/export/html', [ExportControllers\PageExportApiController::class, 'exportHtml']);
|
||||
Route::get('pages/{id}/export/pdf', [ExportControllers\PageExportApiController::class, 'exportPdf']);
|
||||
Route::get('pages/{id}/export/plaintext', [ExportControllers\PageExportApiController::class, 'exportPlainText']);
|
||||
Route::get('pages/{id}/export/markdown', [ExportControllers\PageExportApiController::class, 'exportMarkdown']);
|
||||
|
||||
Route::get('image-gallery', [ImageGalleryApiController::class, 'list']);
|
||||
Route::post('image-gallery', [ImageGalleryApiController::class, 'create']);
|
||||
|
@ -7,6 +7,7 @@ use BookStack\Api\UserApiTokenController;
|
||||
use BookStack\App\HomeController;
|
||||
use BookStack\App\MetaController;
|
||||
use BookStack\Entities\Controllers as EntityControllers;
|
||||
use BookStack\Exports\Controllers as ExportControllers;
|
||||
use BookStack\Http\Middleware\VerifyCsrfToken;
|
||||
use BookStack\Permissions\PermissionsController;
|
||||
use BookStack\References\ReferenceController;
|
||||
@ -74,11 +75,11 @@ Route::middleware('auth')->group(function () {
|
||||
Route::get('/books/{bookSlug}/sort', [EntityControllers\BookSortController::class, 'show']);
|
||||
Route::put('/books/{bookSlug}/sort', [EntityControllers\BookSortController::class, 'update']);
|
||||
Route::get('/books/{slug}/references', [ReferenceController::class, 'book']);
|
||||
Route::get('/books/{bookSlug}/export/html', [EntityControllers\BookExportController::class, 'html']);
|
||||
Route::get('/books/{bookSlug}/export/pdf', [EntityControllers\BookExportController::class, 'pdf']);
|
||||
Route::get('/books/{bookSlug}/export/markdown', [EntityControllers\BookExportController::class, 'markdown']);
|
||||
Route::get('/books/{bookSlug}/export/zip', [EntityControllers\BookExportController::class, 'zip']);
|
||||
Route::get('/books/{bookSlug}/export/plaintext', [EntityControllers\BookExportController::class, 'plainText']);
|
||||
Route::get('/books/{bookSlug}/export/html', [ExportControllers\BookExportController::class, 'html']);
|
||||
Route::get('/books/{bookSlug}/export/pdf', [ExportControllers\BookExportController::class, 'pdf']);
|
||||
Route::get('/books/{bookSlug}/export/markdown', [ExportControllers\BookExportController::class, 'markdown']);
|
||||
Route::get('/books/{bookSlug}/export/zip', [ExportControllers\BookExportController::class, 'zip']);
|
||||
Route::get('/books/{bookSlug}/export/plaintext', [ExportControllers\BookExportController::class, 'plainText']);
|
||||
|
||||
// Pages
|
||||
Route::get('/books/{bookSlug}/create-page', [EntityControllers\PageController::class, 'create']);
|
||||
@ -86,10 +87,10 @@ Route::middleware('auth')->group(function () {
|
||||
Route::get('/books/{bookSlug}/draft/{pageId}', [EntityControllers\PageController::class, 'editDraft']);
|
||||
Route::post('/books/{bookSlug}/draft/{pageId}', [EntityControllers\PageController::class, 'store']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}', [EntityControllers\PageController::class, 'show']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/pdf', [EntityControllers\PageExportController::class, 'pdf']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/html', [EntityControllers\PageExportController::class, 'html']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/markdown', [EntityControllers\PageExportController::class, 'markdown']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/plaintext', [EntityControllers\PageExportController::class, 'plainText']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/pdf', [ExportControllers\PageExportController::class, 'pdf']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/html', [ExportControllers\PageExportController::class, 'html']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/markdown', [ExportControllers\PageExportController::class, 'markdown']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/export/plaintext', [ExportControllers\PageExportController::class, 'plainText']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/edit', [EntityControllers\PageController::class, 'edit']);
|
||||
Route::get('/books/{bookSlug}/page/{pageSlug}/move', [EntityControllers\PageController::class, 'showMove']);
|
||||
Route::put('/books/{bookSlug}/page/{pageSlug}/move', [EntityControllers\PageController::class, 'move']);
|
||||
@ -126,10 +127,10 @@ Route::middleware('auth')->group(function () {
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/edit', [EntityControllers\ChapterController::class, 'edit']);
|
||||
Route::post('/books/{bookSlug}/chapter/{chapterSlug}/convert-to-book', [EntityControllers\ChapterController::class, 'convertToBook']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/permissions', [PermissionsController::class, 'showForChapter']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/pdf', [EntityControllers\ChapterExportController::class, 'pdf']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/html', [EntityControllers\ChapterExportController::class, 'html']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/markdown', [EntityControllers\ChapterExportController::class, 'markdown']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/plaintext', [EntityControllers\ChapterExportController::class, 'plainText']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/pdf', [ExportControllers\ChapterExportController::class, 'pdf']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/html', [ExportControllers\ChapterExportController::class, 'html']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/markdown', [ExportControllers\ChapterExportController::class, 'markdown']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/export/plaintext', [ExportControllers\ChapterExportController::class, 'plainText']);
|
||||
Route::put('/books/{bookSlug}/chapter/{chapterSlug}/permissions', [PermissionsController::class, 'updateForChapter']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/references', [ReferenceController::class, 'chapter']);
|
||||
Route::get('/books/{bookSlug}/chapter/{chapterSlug}/delete', [EntityControllers\ChapterController::class, 'showDelete']);
|
||||
|
@ -5,8 +5,8 @@ namespace Tests\Entity;
|
||||
use BookStack\Entities\Models\Book;
|
||||
use BookStack\Entities\Models\Chapter;
|
||||
use BookStack\Entities\Models\Page;
|
||||
use BookStack\Entities\Tools\PdfGenerator;
|
||||
use BookStack\Exceptions\PdfExportException;
|
||||
use BookStack\Exports\PdfGenerator;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user