Skip to content

Commit 2442829

Browse files
committed
Merge branch 'development' of github.com:BookStackApp/BookStack into development
2 parents 795b281 + 31706ea commit 2442829

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+793
-503
lines changed

app/Activity/Models/Tag.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
* @property int $id
1313
* @property string $name
1414
* @property string $value
15+
* @property int $entity_id
16+
* @property string $entity_type
1517
* @property int $order
1618
*/
1719
class Tag extends Model

app/Activity/Tools/TagClassGenerator.php

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
namespace BookStack\Activity\Tools;
44

55
use BookStack\Activity\Models\Tag;
6+
use BookStack\Entities\Models\BookChild;
7+
use BookStack\Entities\Models\Entity;
8+
use BookStack\Entities\Models\Page;
69

710
class TagClassGenerator
811
{
9-
protected array $tags;
10-
11-
/**
12-
* @param Tag[] $tags
13-
*/
14-
public function __construct(array $tags)
15-
{
16-
$this->tags = $tags;
12+
public function __construct(
13+
protected Entity $entity
14+
) {
1715
}
1816

1917
/**
@@ -22,14 +20,23 @@ public function __construct(array $tags)
2220
public function generate(): array
2321
{
2422
$classes = [];
23+
$tags = $this->entity->tags->all();
24+
25+
foreach ($tags as $tag) {
26+
array_push($classes, ...$this->generateClassesForTag($tag));
27+
}
28+
29+
if ($this->entity instanceof BookChild && userCan('view', $this->entity->book)) {
30+
$bookTags = $this->entity->book->tags;
31+
foreach ($bookTags as $bookTag) {
32+
array_push($classes, ...$this->generateClassesForTag($bookTag, 'book-'));
33+
}
34+
}
2535

26-
foreach ($this->tags as $tag) {
27-
$name = $this->normalizeTagClassString($tag->name);
28-
$value = $this->normalizeTagClassString($tag->value);
29-
$classes[] = 'tag-name-' . $name;
30-
if ($value) {
31-
$classes[] = 'tag-value-' . $value;
32-
$classes[] = 'tag-pair-' . $name . '-' . $value;
36+
if ($this->entity instanceof Page && $this->entity->chapter && userCan('view', $this->entity->chapter)) {
37+
$chapterTags = $this->entity->chapter->tags;
38+
foreach ($chapterTags as $chapterTag) {
39+
array_push($classes, ...$this->generateClassesForTag($chapterTag, 'chapter-'));
3340
}
3441
}
3542

@@ -41,6 +48,22 @@ public function generateAsString(): string
4148
return implode(' ', $this->generate());
4249
}
4350

51+
/**
52+
* @return string[]
53+
*/
54+
protected function generateClassesForTag(Tag $tag, string $prefix = ''): array
55+
{
56+
$classes = [];
57+
$name = $this->normalizeTagClassString($tag->name);
58+
$value = $this->normalizeTagClassString($tag->value);
59+
$classes[] = "{$prefix}tag-name-{$name}";
60+
if ($value) {
61+
$classes[] = "{$prefix}tag-value-{$value}";
62+
$classes[] = "{$prefix}tag-pair-{$name}-{$value}";
63+
}
64+
return $classes;
65+
}
66+
4467
protected function normalizeTagClassString(string $value): string
4568
{
4669
$value = str_replace(' ', '', strtolower($value));

app/Entities/Controllers/BookController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use BookStack\Facades\Activity;
1919
use BookStack\Http\Controller;
2020
use BookStack\References\ReferenceFetcher;
21+
use BookStack\Util\DatabaseTransaction;
2122
use BookStack\Util\SimpleListOptions;
2223
use Illuminate\Http\Request;
2324
use Illuminate\Validation\ValidationException;
@@ -263,7 +264,9 @@ public function convertToShelf(HierarchyTransformer $transformer, string $bookSl
263264
$this->checkPermission('bookshelf-create-all');
264265
$this->checkPermission('book-create-all');
265266

266-
$shelf = $transformer->transformBookToShelf($book);
267+
$shelf = (new DatabaseTransaction(function () use ($book, $transformer) {
268+
return $transformer->transformBookToShelf($book);
269+
}))->run();
267270

268271
return redirect($shelf->getUrl());
269272
}

app/Entities/Controllers/ChapterController.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use BookStack\Exceptions\PermissionsException;
1919
use BookStack\Http\Controller;
2020
use BookStack\References\ReferenceFetcher;
21+
use BookStack\Util\DatabaseTransaction;
2122
use Illuminate\Http\Request;
2223
use Illuminate\Validation\ValidationException;
2324
use Throwable;
@@ -269,7 +270,9 @@ public function convertToBook(HierarchyTransformer $transformer, string $bookSlu
269270
$this->checkOwnablePermission('chapter-delete', $chapter);
270271
$this->checkPermission('book-create-all');
271272

272-
$book = $transformer->transformChapterToBook($chapter);
273+
$book = (new DatabaseTransaction(function () use ($chapter, $transformer) {
274+
return $transformer->transformChapterToBook($chapter);
275+
}))->run();
273276

274277
return redirect($book->getUrl());
275278
}

app/Entities/Repos/BaseRepo.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ public function update(Entity $entity, array $input)
7777
$entity->touch();
7878
}
7979

80-
$entity->rebuildPermissions();
8180
$entity->indexForSearch();
8281
$this->referenceStore->updateForEntity($entity);
8382

@@ -139,7 +138,7 @@ public function updateDefaultTemplate(Book|Chapter $entity, int $templateId): vo
139138

140139
/**
141140
* Sort the parent of the given entity, if any auto sort actions are set for it.
142-
* Typical ran during create/update/insert events.
141+
* Typically ran during create/update/insert events.
143142
*/
144143
public function sortParent(Entity $entity): void
145144
{

app/Entities/Repos/BookRepo.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use BookStack\Facades\Activity;
1111
use BookStack\Sorting\SortRule;
1212
use BookStack\Uploads\ImageRepo;
13+
use BookStack\Util\DatabaseTransaction;
1314
use Exception;
1415
use Illuminate\Http\UploadedFile;
1516

@@ -28,19 +29,22 @@ public function __construct(
2829
*/
2930
public function create(array $input): Book
3031
{
31-
$book = new Book();
32-
$this->baseRepo->create($book, $input);
33-
$this->baseRepo->updateCoverImage($book, $input['image'] ?? null);
34-
$this->baseRepo->updateDefaultTemplate($book, intval($input['default_template_id'] ?? null));
35-
Activity::add(ActivityType::BOOK_CREATE, $book);
32+
return (new DatabaseTransaction(function () use ($input) {
33+
$book = new Book();
3634

37-
$defaultBookSortSetting = intval(setting('sorting-book-default', '0'));
38-
if ($defaultBookSortSetting && SortRule::query()->find($defaultBookSortSetting)) {
39-
$book->sort_rule_id = $defaultBookSortSetting;
40-
$book->save();
41-
}
35+
$this->baseRepo->create($book, $input);
36+
$this->baseRepo->updateCoverImage($book, $input['image'] ?? null);
37+
$this->baseRepo->updateDefaultTemplate($book, intval($input['default_template_id'] ?? null));
38+
Activity::add(ActivityType::BOOK_CREATE, $book);
4239

43-
return $book;
40+
$defaultBookSortSetting = intval(setting('sorting-book-default', '0'));
41+
if ($defaultBookSortSetting && SortRule::query()->find($defaultBookSortSetting)) {
42+
$book->sort_rule_id = $defaultBookSortSetting;
43+
$book->save();
44+
}
45+
46+
return $book;
47+
}))->run();
4448
}
4549

4650
/**

app/Entities/Repos/BookshelfRepo.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use BookStack\Entities\Queries\BookQueries;
88
use BookStack\Entities\Tools\TrashCan;
99
use BookStack\Facades\Activity;
10+
use BookStack\Util\DatabaseTransaction;
1011
use Exception;
1112

1213
class BookshelfRepo
@@ -23,13 +24,14 @@ public function __construct(
2324
*/
2425
public function create(array $input, array $bookIds): Bookshelf
2526
{
26-
$shelf = new Bookshelf();
27-
$this->baseRepo->create($shelf, $input);
28-
$this->baseRepo->updateCoverImage($shelf, $input['image'] ?? null);
29-
$this->updateBooks($shelf, $bookIds);
30-
Activity::add(ActivityType::BOOKSHELF_CREATE, $shelf);
31-
32-
return $shelf;
27+
return (new DatabaseTransaction(function () use ($input, $bookIds) {
28+
$shelf = new Bookshelf();
29+
$this->baseRepo->create($shelf, $input);
30+
$this->baseRepo->updateCoverImage($shelf, $input['image'] ?? null);
31+
$this->updateBooks($shelf, $bookIds);
32+
Activity::add(ActivityType::BOOKSHELF_CREATE, $shelf);
33+
return $shelf;
34+
}))->run();
3335
}
3436

3537
/**

app/Entities/Repos/ChapterRepo.php

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use BookStack\Exceptions\MoveOperationException;
1212
use BookStack\Exceptions\PermissionsException;
1313
use BookStack\Facades\Activity;
14+
use BookStack\Util\DatabaseTransaction;
1415
use Exception;
1516

1617
class ChapterRepo
@@ -27,16 +28,18 @@ public function __construct(
2728
*/
2829
public function create(array $input, Book $parentBook): Chapter
2930
{
30-
$chapter = new Chapter();
31-
$chapter->book_id = $parentBook->id;
32-
$chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
33-
$this->baseRepo->create($chapter, $input);
34-
$this->baseRepo->updateDefaultTemplate($chapter, intval($input['default_template_id'] ?? null));
35-
Activity::add(ActivityType::CHAPTER_CREATE, $chapter);
36-
37-
$this->baseRepo->sortParent($chapter);
38-
39-
return $chapter;
31+
return (new DatabaseTransaction(function () use ($input, $parentBook) {
32+
$chapter = new Chapter();
33+
$chapter->book_id = $parentBook->id;
34+
$chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
35+
$this->baseRepo->create($chapter, $input);
36+
$this->baseRepo->updateDefaultTemplate($chapter, intval($input['default_template_id'] ?? null));
37+
Activity::add(ActivityType::CHAPTER_CREATE, $chapter);
38+
39+
$this->baseRepo->sortParent($chapter);
40+
41+
return $chapter;
42+
}))->run();
4043
}
4144

4245
/**
@@ -88,12 +91,14 @@ public function move(Chapter $chapter, string $parentIdentifier): Book
8891
throw new PermissionsException('User does not have permission to create a chapter within the chosen book');
8992
}
9093

91-
$chapter->changeBook($parent->id);
92-
$chapter->rebuildPermissions();
93-
Activity::add(ActivityType::CHAPTER_MOVE, $chapter);
94+
return (new DatabaseTransaction(function () use ($chapter, $parent) {
95+
$chapter->changeBook($parent->id);
96+
$chapter->rebuildPermissions();
97+
Activity::add(ActivityType::CHAPTER_MOVE, $chapter);
9498

95-
$this->baseRepo->sortParent($chapter);
99+
$this->baseRepo->sortParent($chapter);
96100

97-
return $parent;
101+
return $parent;
102+
}))->run();
98103
}
99104
}

app/Entities/Repos/PageRepo.php

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use BookStack\Facades\Activity;
1919
use BookStack\References\ReferenceStore;
2020
use BookStack\References\ReferenceUpdater;
21+
use BookStack\Util\DatabaseTransaction;
2122
use Exception;
2223

2324
class PageRepo
@@ -61,8 +62,10 @@ public function getNewDraftPage(Entity $parent)
6162
]);
6263
}
6364

64-
$page->save();
65-
$page->refresh()->rebuildPermissions();
65+
(new DatabaseTransaction(function () use ($page) {
66+
$page->save();
67+
$page->refresh()->rebuildPermissions();
68+
}))->run();
6669

6770
return $page;
6871
}
@@ -72,26 +75,29 @@ public function getNewDraftPage(Entity $parent)
7275
*/
7376
public function publishDraft(Page $draft, array $input): Page
7477
{
75-
$draft->draft = false;
76-
$draft->revision_count = 1;
77-
$draft->priority = $this->getNewPriority($draft);
78-
$this->updateTemplateStatusAndContentFromInput($draft, $input);
79-
$this->baseRepo->update($draft, $input);
80-
81-
$summary = trim($input['summary'] ?? '') ?: trans('entities.pages_initial_revision');
82-
$this->revisionRepo->storeNewForPage($draft, $summary);
83-
$draft->refresh();
84-
85-
Activity::add(ActivityType::PAGE_CREATE, $draft);
86-
$this->baseRepo->sortParent($draft);
87-
88-
return $draft;
78+
return (new DatabaseTransaction(function () use ($draft, $input) {
79+
$draft->draft = false;
80+
$draft->revision_count = 1;
81+
$draft->priority = $this->getNewPriority($draft);
82+
$this->updateTemplateStatusAndContentFromInput($draft, $input);
83+
$this->baseRepo->update($draft, $input);
84+
$draft->rebuildPermissions();
85+
86+
$summary = trim($input['summary'] ?? '') ?: trans('entities.pages_initial_revision');
87+
$this->revisionRepo->storeNewForPage($draft, $summary);
88+
$draft->refresh();
89+
90+
Activity::add(ActivityType::PAGE_CREATE, $draft);
91+
$this->baseRepo->sortParent($draft);
92+
93+
return $draft;
94+
}))->run();
8995
}
9096

9197
/**
9298
* Directly update the content for the given page from the provided input.
9399
* Used for direct content access in a way that performs required changes
94-
* (Search index & reference regen) without performing an official update.
100+
* (Search index and reference regen) without performing an official update.
95101
*/
96102
public function setContentFromInput(Page $page, array $input): void
97103
{
@@ -116,7 +122,7 @@ public function update(Page $page, array $input): Page
116122
$page->revision_count++;
117123
$page->save();
118124

119-
// Remove all update drafts for this user & page.
125+
// Remove all update drafts for this user and page.
120126
$this->revisionRepo->deleteDraftsForCurrentUser($page);
121127

122128
// Save a revision after updating
@@ -269,16 +275,18 @@ public function move(Page $page, string $parentIdentifier): Entity
269275
throw new PermissionsException('User does not have permission to create a page within the new parent');
270276
}
271277

272-
$page->chapter_id = ($parent instanceof Chapter) ? $parent->id : null;
273-
$newBookId = ($parent instanceof Chapter) ? $parent->book->id : $parent->id;
274-
$page->changeBook($newBookId);
275-
$page->rebuildPermissions();
278+
return (new DatabaseTransaction(function () use ($page, $parent) {
279+
$page->chapter_id = ($parent instanceof Chapter) ? $parent->id : null;
280+
$newBookId = ($parent instanceof Chapter) ? $parent->book->id : $parent->id;
281+
$page->changeBook($newBookId);
282+
$page->rebuildPermissions();
276283

277-
Activity::add(ActivityType::PAGE_MOVE, $page);
284+
Activity::add(ActivityType::PAGE_MOVE, $page);
278285

279-
$this->baseRepo->sortParent($page);
286+
$this->baseRepo->sortParent($page);
280287

281-
return $parent;
288+
return $parent;
289+
}))->run();
282290
}
283291

284292
/**

app/Entities/Tools/HierarchyTransformer.php

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,12 @@
1313

1414
class HierarchyTransformer
1515
{
16-
protected BookRepo $bookRepo;
17-
protected BookshelfRepo $shelfRepo;
18-
protected Cloner $cloner;
19-
protected TrashCan $trashCan;
20-
21-
public function __construct(BookRepo $bookRepo, BookshelfRepo $shelfRepo, Cloner $cloner, TrashCan $trashCan)
22-
{
23-
$this->bookRepo = $bookRepo;
24-
$this->shelfRepo = $shelfRepo;
25-
$this->cloner = $cloner;
26-
$this->trashCan = $trashCan;
16+
public function __construct(
17+
protected BookRepo $bookRepo,
18+
protected BookshelfRepo $shelfRepo,
19+
protected Cloner $cloner,
20+
protected TrashCan $trashCan
21+
) {
2722
}
2823

2924
/**

0 commit comments

Comments
 (0)