Skip to content

Commit 92cfde4

Browse files
committed
ZIP Imports: Added full contents view to import display
Reduced import data will now be stored on the import itself, instead of storing a set of totals.
1 parent 14578c2 commit 92cfde4

20 files changed

+303
-105
lines changed

app/Exports/Controllers/ImportController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,13 @@ public function show(int $id)
6565
{
6666
$import = $this->imports->findVisible($id);
6767

68+
// dd($import->decodeMetadata());
69+
6870
$this->setPageTitle(trans('entities.import_continue'));
6971

7072
return view('exports.import-show', [
7173
'import' => $import,
74+
'data' => $import->decodeMetadata(),
7275
]);
7376
}
7477

@@ -89,7 +92,7 @@ public function run(int $id, Request $request)
8992
// TODO - Validate again before
9093
// TODO - Check permissions before (create for main item, create for children, create for related items [image, attachments])
9194
// TODO - Redirect to result
92-
// TOOD - Or redirect back with errors
95+
// TODO - Or redirect back with errors
9396
}
9497

9598
/**

app/Exports/Import.php

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
namespace BookStack\Exports;
44

55
use BookStack\Activity\Models\Loggable;
6+
use BookStack\Exports\ZipExports\Models\ZipExportBook;
7+
use BookStack\Exports\ZipExports\Models\ZipExportChapter;
8+
use BookStack\Exports\ZipExports\Models\ZipExportPage;
69
use BookStack\Users\Models\User;
710
use Carbon\Carbon;
811
use Illuminate\Database\Eloquent\Factories\HasFactory;
@@ -14,9 +17,8 @@
1417
* @property string $path
1518
* @property string $name
1619
* @property int $size - ZIP size in bytes
17-
* @property int $book_count
18-
* @property int $chapter_count
19-
* @property int $page_count
20+
* @property string $type
21+
* @property string $metadata
2022
* @property int $created_by
2123
* @property Carbon $created_at
2224
* @property Carbon $updated_at
@@ -26,24 +28,6 @@ class Import extends Model implements Loggable
2628
{
2729
use HasFactory;
2830

29-
public const TYPE_BOOK = 'book';
30-
public const TYPE_CHAPTER = 'chapter';
31-
public const TYPE_PAGE = 'page';
32-
33-
/**
34-
* Get the type (model) that this import is intended to be.
35-
*/
36-
public function getType(): string
37-
{
38-
if ($this->book_count === 1) {
39-
return self::TYPE_BOOK;
40-
} elseif ($this->chapter_count === 1) {
41-
return self::TYPE_CHAPTER;
42-
}
43-
44-
return self::TYPE_PAGE;
45-
}
46-
4731
public function getSizeString(): string
4832
{
4933
$mb = round($this->size / 1000000, 2);
@@ -68,4 +52,15 @@ public function createdBy(): BelongsTo
6852
{
6953
return $this->belongsTo(User::class, 'created_by');
7054
}
55+
56+
public function decodeMetadata(): ZipExportBook|ZipExportChapter|ZipExportPage|null
57+
{
58+
$metadataArray = json_decode($this->metadata, true);
59+
return match ($this->type) {
60+
'book' => ZipExportBook::fromArray($metadataArray),
61+
'chapter' => ZipExportChapter::fromArray($metadataArray),
62+
'page' => ZipExportPage::fromArray($metadataArray),
63+
default => null,
64+
};
65+
}
7166
}

app/Exports/ImportRepo.php

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22

33
namespace BookStack\Exports;
44

5+
use BookStack\Exceptions\FileUploadException;
6+
use BookStack\Exceptions\ZipExportException;
57
use BookStack\Exceptions\ZipValidationException;
8+
use BookStack\Exports\ZipExports\Models\ZipExportBook;
9+
use BookStack\Exports\ZipExports\Models\ZipExportChapter;
10+
use BookStack\Exports\ZipExports\Models\ZipExportPage;
611
use BookStack\Exports\ZipExports\ZipExportReader;
712
use BookStack\Exports\ZipExports\ZipExportValidator;
813
use BookStack\Uploads\FileStorage;
@@ -41,6 +46,11 @@ public function findVisible(int $id): Import
4146
return $query->findOrFail($id);
4247
}
4348

49+
/**
50+
* @throws FileUploadException
51+
* @throws ZipValidationException
52+
* @throws ZipExportException
53+
*/
4454
public function storeFromUpload(UploadedFile $file): Import
4555
{
4656
$zipPath = $file->getRealPath();
@@ -50,15 +60,23 @@ public function storeFromUpload(UploadedFile $file): Import
5060
throw new ZipValidationException($errors);
5161
}
5262

53-
$zipEntityInfo = (new ZipExportReader($zipPath))->getEntityInfo();
63+
$reader = new ZipExportReader($zipPath);
64+
$exportModel = $reader->decodeDataToExportModel();
65+
5466
$import = new Import();
55-
$import->name = $zipEntityInfo['name'];
56-
$import->book_count = $zipEntityInfo['book_count'];
57-
$import->chapter_count = $zipEntityInfo['chapter_count'];
58-
$import->page_count = $zipEntityInfo['page_count'];
67+
$import->type = match (get_class($exportModel)) {
68+
ZipExportPage::class => 'page',
69+
ZipExportChapter::class => 'chapter',
70+
ZipExportBook::class => 'book',
71+
};
72+
73+
$import->name = $exportModel->name;
5974
$import->created_by = user()->id;
6075
$import->size = filesize($zipPath);
6176

77+
$exportModel->metadataOnly();
78+
$import->metadata = json_encode($exportModel);
79+
6280
$path = $this->storage->uploadFile(
6381
$file,
6482
'uploads/files/imports/',
@@ -72,6 +90,13 @@ public function storeFromUpload(UploadedFile $file): Import
7290
return $import;
7391
}
7492

93+
public function runImport(Import $import, ?string $parent = null)
94+
{
95+
// TODO - Download import zip (if needed)
96+
// TODO - Validate zip file again
97+
// TODO - Check permissions before (create for main item, create for children, create for related items [image, attachments])
98+
}
99+
75100
public function deleteImport(Import $import): void
76101
{
77102
$this->storage->delete($import->path);

app/Exports/ZipExports/Models/ZipExportAttachment.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ class ZipExportAttachment extends ZipExportModel
1414
public ?string $link = null;
1515
public ?string $file = null;
1616

17+
public function metadataOnly(): void
18+
{
19+
$this->order = $this->link = $this->file = null;
20+
}
21+
1722
public static function fromModel(Attachment $model, ZipExportFiles $files): self
1823
{
1924
$instance = new self();
@@ -49,4 +54,17 @@ public static function validate(ZipValidationHelper $context, array $data): arra
4954

5055
return $context->validateData($data, $rules);
5156
}
57+
58+
public static function fromArray(array $data): self
59+
{
60+
$model = new self();
61+
62+
$model->id = $data['id'] ?? null;
63+
$model->name = $data['name'];
64+
$model->order = isset($data['order']) ? intval($data['order']) : null;
65+
$model->link = $data['link'] ?? null;
66+
$model->file = $data['file'] ?? null;
67+
68+
return $model;
69+
}
5270
}

app/Exports/ZipExports/Models/ZipExportBook.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ class ZipExportBook extends ZipExportModel
2121
/** @var ZipExportTag[] */
2222
public array $tags = [];
2323

24+
public function metadataOnly(): void
25+
{
26+
$this->description_html = $this->cover = null;
27+
28+
foreach ($this->chapters as $chapter) {
29+
$chapter->metadataOnly();
30+
}
31+
foreach ($this->pages as $page) {
32+
$page->metadataOnly();
33+
}
34+
foreach ($this->tags as $tag) {
35+
$tag->metadataOnly();
36+
}
37+
}
38+
2439
public static function fromModel(Book $model, ZipExportFiles $files): self
2540
{
2641
$instance = new self();
@@ -71,4 +86,19 @@ public static function validate(ZipValidationHelper $context, array $data): arra
7186

7287
return $errors;
7388
}
89+
90+
public static function fromArray(array $data): self
91+
{
92+
$model = new self();
93+
94+
$model->id = $data['id'] ?? null;
95+
$model->name = $data['name'];
96+
$model->description_html = $data['description_html'] ?? null;
97+
$model->cover = $data['cover'] ?? null;
98+
$model->tags = ZipExportTag::fromManyArray($data['tags'] ?? []);
99+
$model->pages = ZipExportPage::fromManyArray($data['pages'] ?? []);
100+
$model->chapters = ZipExportChapter::fromManyArray($data['chapters'] ?? []);
101+
102+
return $model;
103+
}
74104
}

app/Exports/ZipExports/Models/ZipExportChapter.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ class ZipExportChapter extends ZipExportModel
1818
/** @var ZipExportTag[] */
1919
public array $tags = [];
2020

21+
public function metadataOnly(): void
22+
{
23+
$this->description_html = $this->priority = null;
24+
25+
foreach ($this->pages as $page) {
26+
$page->metadataOnly();
27+
}
28+
foreach ($this->tags as $tag) {
29+
$tag->metadataOnly();
30+
}
31+
}
32+
2133
public static function fromModel(Chapter $model, ZipExportFiles $files): self
2234
{
2335
$instance = new self();
@@ -61,4 +73,18 @@ public static function validate(ZipValidationHelper $context, array $data): arra
6173

6274
return $errors;
6375
}
76+
77+
public static function fromArray(array $data): self
78+
{
79+
$model = new self();
80+
81+
$model->id = $data['id'] ?? null;
82+
$model->name = $data['name'];
83+
$model->description_html = $data['description_html'] ?? null;
84+
$model->priority = isset($data['priority']) ? intval($data['priority']) : null;
85+
$model->tags = ZipExportTag::fromManyArray($data['tags'] ?? []);
86+
$model->pages = ZipExportPage::fromManyArray($data['pages'] ?? []);
87+
88+
return $model;
89+
}
6490
}

app/Exports/ZipExports/Models/ZipExportImage.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public static function fromModel(Image $model, ZipExportFiles $files): self
2525
return $instance;
2626
}
2727

28+
public function metadataOnly(): void
29+
{
30+
//
31+
}
32+
2833
public static function validate(ZipValidationHelper $context, array $data): array
2934
{
3035
$rules = [
@@ -36,4 +41,16 @@ public static function validate(ZipValidationHelper $context, array $data): arra
3641

3742
return $context->validateData($data, $rules);
3843
}
44+
45+
public static function fromArray(array $data): self
46+
{
47+
$model = new self();
48+
49+
$model->id = $data['id'] ?? null;
50+
$model->name = $data['name'];
51+
$model->file = $data['file'];
52+
$model->type = $data['type'];
53+
54+
return $model;
55+
}
3956
}

app/Exports/ZipExports/Models/ZipExportModel.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,32 @@ public function jsonSerialize(): array
2626
* item in the array for its own validation messages.
2727
*/
2828
abstract public static function validate(ZipValidationHelper $context, array $data): array;
29+
30+
/**
31+
* Decode the array of data into this export model.
32+
*/
33+
abstract public static function fromArray(array $data): self;
34+
35+
/**
36+
* Decode an array of array data into an array of export models.
37+
* @param array[] $data
38+
* @return self[]
39+
*/
40+
public static function fromManyArray(array $data): array
41+
{
42+
$results = [];
43+
foreach ($data as $item) {
44+
$results[] = static::fromArray($item);
45+
}
46+
return $results;
47+
}
48+
49+
/**
50+
* Remove additional content in this model to reduce it down
51+
* to just essential id/name values for identification.
52+
*
53+
* The result of this may be something that does not pass validation, but is
54+
* simple for the purpose of creating a contents.
55+
*/
56+
abstract public function metadataOnly(): void;
2957
}

app/Exports/ZipExports/Models/ZipExportPage.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ class ZipExportPage extends ZipExportModel
2121
/** @var ZipExportTag[] */
2222
public array $tags = [];
2323

24+
public function metadataOnly(): void
25+
{
26+
$this->html = $this->markdown = $this->priority = null;
27+
28+
foreach ($this->attachments as $attachment) {
29+
$attachment->metadataOnly();
30+
}
31+
foreach ($this->images as $image) {
32+
$image->metadataOnly();
33+
}
34+
foreach ($this->tags as $tag) {
35+
$tag->metadataOnly();
36+
}
37+
}
38+
2439
public static function fromModel(Page $model, ZipExportFiles $files): self
2540
{
2641
$instance = new self();
@@ -70,4 +85,20 @@ public static function validate(ZipValidationHelper $context, array $data): arra
7085

7186
return $errors;
7287
}
88+
89+
public static function fromArray(array $data): self
90+
{
91+
$model = new self();
92+
93+
$model->id = $data['id'] ?? null;
94+
$model->name = $data['name'];
95+
$model->html = $data['html'] ?? null;
96+
$model->markdown = $data['markdown'] ?? null;
97+
$model->priority = isset($data['priority']) ? intval($data['priority']) : null;
98+
$model->attachments = ZipExportAttachment::fromManyArray($data['attachments'] ?? []);
99+
$model->images = ZipExportImage::fromManyArray($data['images'] ?? []);
100+
$model->tags = ZipExportTag::fromManyArray($data['tags'] ?? []);
101+
102+
return $model;
103+
}
73104
}

app/Exports/ZipExports/Models/ZipExportTag.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ class ZipExportTag extends ZipExportModel
1111
public ?string $value = null;
1212
public ?int $order = null;
1313

14+
public function metadataOnly(): void
15+
{
16+
$this->value = $this->order = null;
17+
}
18+
1419
public static function fromModel(Tag $model): self
1520
{
1621
$instance = new self();
@@ -36,4 +41,15 @@ public static function validate(ZipValidationHelper $context, array $data): arra
3641

3742
return $context->validateData($data, $rules);
3843
}
44+
45+
public static function fromArray(array $data): self
46+
{
47+
$model = new self();
48+
49+
$model->name = $data['name'];
50+
$model->value = $data['value'] ?? null;
51+
$model->order = isset($data['order']) ? intval($data['order']) : null;
52+
53+
return $model;
54+
}
3955
}

0 commit comments

Comments
 (0)