Skip to content

Commit 529f7bd

Browse files
authored
Merge pull request #4729 from BookStackApp/description_wysiwyg
Simple WYSIWYG for description fields and comments
2 parents fc2e8ed + 3668949 commit 529f7bd

File tree

85 files changed

+1201
-334
lines changed

Some content is hidden

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

85 files changed

+1201
-334
lines changed

app/Console/Commands/RegenerateReferencesCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function handle(ReferenceStore $references): int
3434
DB::setDefaultConnection($this->option('database'));
3535
}
3636

37-
$references->updateForAllPages();
37+
$references->updateForAll();
3838

3939
DB::setDefaultConnection($connection);
4040

app/Console/Commands/UpdateUrlCommand.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public function handle(Connection $db): int
4646
$columnsToUpdateByTable = [
4747
'attachments' => ['path'],
4848
'pages' => ['html', 'text', 'markdown'],
49+
'chapters' => ['description_html'],
50+
'books' => ['description_html'],
51+
'bookshelves' => ['description_html'],
4952
'images' => ['url'],
5053
'settings' => ['value'],
5154
'comments' => ['html', 'text'],

app/Entities/Controllers/BookApiController.php

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function create(Request $request)
4545

4646
$book = $this->bookRepo->create($requestData);
4747

48-
return response()->json($book);
48+
return response()->json($this->forJsonDisplay($book));
4949
}
5050

5151
/**
@@ -56,9 +56,9 @@ public function create(Request $request)
5656
*/
5757
public function read(string $id)
5858
{
59-
$book = Book::visible()
60-
->with(['tags', 'cover', 'createdBy', 'updatedBy', 'ownedBy'])
61-
->findOrFail($id);
59+
$book = Book::visible()->findOrFail($id);
60+
$book = $this->forJsonDisplay($book);
61+
$book->load(['createdBy', 'updatedBy', 'ownedBy']);
6262

6363
$contents = (new BookContents($book))->getTree(true, false)->all();
6464
$contentsApiData = (new ApiEntityListFormatter($contents))
@@ -89,7 +89,7 @@ public function update(Request $request, string $id)
8989
$requestData = $this->validate($request, $this->rules()['update']);
9090
$book = $this->bookRepo->update($book, $requestData);
9191

92-
return response()->json($book);
92+
return response()->json($this->forJsonDisplay($book));
9393
}
9494

9595
/**
@@ -108,21 +108,35 @@ public function delete(string $id)
108108
return response('', 204);
109109
}
110110

111+
protected function forJsonDisplay(Book $book): Book
112+
{
113+
$book = clone $book;
114+
$book->unsetRelations()->refresh();
115+
116+
$book->load(['tags', 'cover']);
117+
$book->makeVisible('description_html')
118+
->setAttribute('description_html', $book->descriptionHtml());
119+
120+
return $book;
121+
}
122+
111123
protected function rules(): array
112124
{
113125
return [
114126
'create' => [
115-
'name' => ['required', 'string', 'max:255'],
116-
'description' => ['string', 'max:1000'],
117-
'tags' => ['array'],
118-
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
127+
'name' => ['required', 'string', 'max:255'],
128+
'description' => ['string', 'max:1900'],
129+
'description_html' => ['string', 'max:2000'],
130+
'tags' => ['array'],
131+
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
119132
'default_template_id' => ['nullable', 'integer'],
120133
],
121134
'update' => [
122-
'name' => ['string', 'min:1', 'max:255'],
123-
'description' => ['string', 'max:1000'],
124-
'tags' => ['array'],
125-
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
135+
'name' => ['string', 'min:1', 'max:255'],
136+
'description' => ['string', 'max:1900'],
137+
'description_html' => ['string', 'max:2000'],
138+
'tags' => ['array'],
139+
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
126140
'default_template_id' => ['nullable', 'integer'],
127141
],
128142
];

app/Entities/Controllers/BookController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public function store(Request $request, string $shelfSlug = null)
9393
$this->checkPermission('book-create-all');
9494
$validated = $this->validate($request, [
9595
'name' => ['required', 'string', 'max:255'],
96-
'description' => ['string', 'max:1000'],
96+
'description_html' => ['string', 'max:2000'],
9797
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
9898
'tags' => ['array'],
9999
'default_template_id' => ['nullable', 'integer'],
@@ -138,7 +138,7 @@ public function show(Request $request, ActivityQueries $activities, string $slug
138138
'bookParentShelves' => $bookParentShelves,
139139
'watchOptions' => new UserEntityWatchOptions(user(), $book),
140140
'activity' => $activities->entityActivity($book, 20, 1),
141-
'referenceCount' => $this->referenceFetcher->getPageReferenceCountToEntity($book),
141+
'referenceCount' => $this->referenceFetcher->getReferenceCountToEntity($book),
142142
]);
143143
}
144144

@@ -168,7 +168,7 @@ public function update(Request $request, string $slug)
168168

169169
$validated = $this->validate($request, [
170170
'name' => ['required', 'string', 'max:255'],
171-
'description' => ['string', 'max:1000'],
171+
'description_html' => ['string', 'max:2000'],
172172
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
173173
'tags' => ['array'],
174174
'default_template_id' => ['nullable', 'integer'],

app/Entities/Controllers/BookshelfApiController.php

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212

1313
class BookshelfApiController extends ApiController
1414
{
15-
protected BookshelfRepo $bookshelfRepo;
16-
17-
public function __construct(BookshelfRepo $bookshelfRepo)
18-
{
19-
$this->bookshelfRepo = $bookshelfRepo;
15+
public function __construct(
16+
protected BookshelfRepo $bookshelfRepo
17+
) {
2018
}
2119

2220
/**
@@ -48,20 +46,22 @@ public function create(Request $request)
4846
$bookIds = $request->get('books', []);
4947
$shelf = $this->bookshelfRepo->create($requestData, $bookIds);
5048

51-
return response()->json($shelf);
49+
return response()->json($this->forJsonDisplay($shelf));
5250
}
5351

5452
/**
5553
* View the details of a single shelf.
5654
*/
5755
public function read(string $id)
5856
{
59-
$shelf = Bookshelf::visible()->with([
60-
'tags', 'cover', 'createdBy', 'updatedBy', 'ownedBy',
57+
$shelf = Bookshelf::visible()->findOrFail($id);
58+
$shelf = $this->forJsonDisplay($shelf);
59+
$shelf->load([
60+
'createdBy', 'updatedBy', 'ownedBy',
6161
'books' => function (BelongsToMany $query) {
6262
$query->scopes('visible')->get(['id', 'name', 'slug']);
6363
},
64-
])->findOrFail($id);
64+
]);
6565

6666
return response()->json($shelf);
6767
}
@@ -86,7 +86,7 @@ public function update(Request $request, string $id)
8686

8787
$shelf = $this->bookshelfRepo->update($shelf, $requestData, $bookIds);
8888

89-
return response()->json($shelf);
89+
return response()->json($this->forJsonDisplay($shelf));
9090
}
9191

9292
/**
@@ -105,22 +105,36 @@ public function delete(string $id)
105105
return response('', 204);
106106
}
107107

108+
protected function forJsonDisplay(Bookshelf $shelf): Bookshelf
109+
{
110+
$shelf = clone $shelf;
111+
$shelf->unsetRelations()->refresh();
112+
113+
$shelf->load(['tags', 'cover']);
114+
$shelf->makeVisible('description_html')
115+
->setAttribute('description_html', $shelf->descriptionHtml());
116+
117+
return $shelf;
118+
}
119+
108120
protected function rules(): array
109121
{
110122
return [
111123
'create' => [
112-
'name' => ['required', 'string', 'max:255'],
113-
'description' => ['string', 'max:1000'],
114-
'books' => ['array'],
115-
'tags' => ['array'],
116-
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
124+
'name' => ['required', 'string', 'max:255'],
125+
'description' => ['string', 'max:1900'],
126+
'description_html' => ['string', 'max:2000'],
127+
'books' => ['array'],
128+
'tags' => ['array'],
129+
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
117130
],
118131
'update' => [
119-
'name' => ['string', 'min:1', 'max:255'],
120-
'description' => ['string', 'max:1000'],
121-
'books' => ['array'],
122-
'tags' => ['array'],
123-
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
132+
'name' => ['string', 'min:1', 'max:255'],
133+
'description' => ['string', 'max:1900'],
134+
'description_html' => ['string', 'max:2000'],
135+
'books' => ['array'],
136+
'tags' => ['array'],
137+
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
124138
],
125139
];
126140
}

app/Entities/Controllers/BookshelfController.php

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,11 @@
1818

1919
class BookshelfController extends Controller
2020
{
21-
protected BookshelfRepo $shelfRepo;
22-
protected ShelfContext $shelfContext;
23-
protected ReferenceFetcher $referenceFetcher;
24-
25-
public function __construct(BookshelfRepo $shelfRepo, ShelfContext $shelfContext, ReferenceFetcher $referenceFetcher)
26-
{
27-
$this->shelfRepo = $shelfRepo;
28-
$this->shelfContext = $shelfContext;
29-
$this->referenceFetcher = $referenceFetcher;
21+
public function __construct(
22+
protected BookshelfRepo $shelfRepo,
23+
protected ShelfContext $shelfContext,
24+
protected ReferenceFetcher $referenceFetcher
25+
) {
3026
}
3127

3228
/**
@@ -81,10 +77,10 @@ public function store(Request $request)
8177
{
8278
$this->checkPermission('bookshelf-create-all');
8379
$validated = $this->validate($request, [
84-
'name' => ['required', 'string', 'max:255'],
85-
'description' => ['string', 'max:1000'],
86-
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
87-
'tags' => ['array'],
80+
'name' => ['required', 'string', 'max:255'],
81+
'description_html' => ['string', 'max:2000'],
82+
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
83+
'tags' => ['array'],
8884
]);
8985

9086
$bookIds = explode(',', $request->get('books', ''));
@@ -129,7 +125,7 @@ public function show(Request $request, ActivityQueries $activities, string $slug
129125
'view' => $view,
130126
'activity' => $activities->entityActivity($shelf, 20, 1),
131127
'listOptions' => $listOptions,
132-
'referenceCount' => $this->referenceFetcher->getPageReferenceCountToEntity($shelf),
128+
'referenceCount' => $this->referenceFetcher->getReferenceCountToEntity($shelf),
133129
]);
134130
}
135131

@@ -164,10 +160,10 @@ public function update(Request $request, string $slug)
164160
$shelf = $this->shelfRepo->getBySlug($slug);
165161
$this->checkOwnablePermission('bookshelf-update', $shelf);
166162
$validated = $this->validate($request, [
167-
'name' => ['required', 'string', 'max:255'],
168-
'description' => ['string', 'max:1000'],
169-
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
170-
'tags' => ['array'],
163+
'name' => ['required', 'string', 'max:255'],
164+
'description_html' => ['string', 'max:2000'],
165+
'image' => array_merge(['nullable'], $this->getImageValidationRules()),
166+
'tags' => ['array'],
171167
]);
172168

173169
if ($request->has('image_reset')) {

app/Entities/Controllers/ChapterApiController.php

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,20 @@ class ChapterApiController extends ApiController
1515
{
1616
protected $rules = [
1717
'create' => [
18-
'book_id' => ['required', 'integer'],
19-
'name' => ['required', 'string', 'max:255'],
20-
'description' => ['string', 'max:1000'],
21-
'tags' => ['array'],
22-
'priority' => ['integer'],
18+
'book_id' => ['required', 'integer'],
19+
'name' => ['required', 'string', 'max:255'],
20+
'description' => ['string', 'max:1900'],
21+
'description_html' => ['string', 'max:2000'],
22+
'tags' => ['array'],
23+
'priority' => ['integer'],
2324
],
2425
'update' => [
25-
'book_id' => ['integer'],
26-
'name' => ['string', 'min:1', 'max:255'],
27-
'description' => ['string', 'max:1000'],
28-
'tags' => ['array'],
29-
'priority' => ['integer'],
26+
'book_id' => ['integer'],
27+
'name' => ['string', 'min:1', 'max:255'],
28+
'description' => ['string', 'max:1900'],
29+
'description_html' => ['string', 'max:2000'],
30+
'tags' => ['array'],
31+
'priority' => ['integer'],
3032
],
3133
];
3234

@@ -61,17 +63,23 @@ public function create(Request $request)
6163

6264
$chapter = $this->chapterRepo->create($requestData, $book);
6365

64-
return response()->json($chapter->load(['tags']));
66+
return response()->json($this->forJsonDisplay($chapter));
6567
}
6668

6769
/**
6870
* View the details of a single chapter.
6971
*/
7072
public function read(string $id)
7173
{
72-
$chapter = Chapter::visible()->with(['tags', 'createdBy', 'updatedBy', 'ownedBy', 'pages' => function (HasMany $query) {
73-
$query->scopes('visible')->get(['id', 'name', 'slug']);
74-
}])->findOrFail($id);
74+
$chapter = Chapter::visible()->findOrFail($id);
75+
$chapter = $this->forJsonDisplay($chapter);
76+
77+
$chapter->load([
78+
'createdBy', 'updatedBy', 'ownedBy',
79+
'pages' => function (HasMany $query) {
80+
$query->scopes('visible')->get(['id', 'name', 'slug']);
81+
}
82+
]);
7583

7684
return response()->json($chapter);
7785
}
@@ -93,7 +101,7 @@ public function update(Request $request, string $id)
93101
try {
94102
$this->chapterRepo->move($chapter, "book:{$requestData['book_id']}");
95103
} catch (Exception $exception) {
96-
if ($exception instanceof PermissionsException) {
104+
if ($exception instanceof PermissionsException) {
97105
$this->showPermissionError();
98106
}
99107

@@ -103,7 +111,7 @@ public function update(Request $request, string $id)
103111

104112
$updatedChapter = $this->chapterRepo->update($chapter, $requestData);
105113

106-
return response()->json($updatedChapter->load(['tags']));
114+
return response()->json($this->forJsonDisplay($updatedChapter));
107115
}
108116

109117
/**
@@ -119,4 +127,16 @@ public function delete(string $id)
119127

120128
return response('', 204);
121129
}
130+
131+
protected function forJsonDisplay(Chapter $chapter): Chapter
132+
{
133+
$chapter = clone $chapter;
134+
$chapter->unsetRelations()->refresh();
135+
136+
$chapter->load(['tags']);
137+
$chapter->makeVisible('description_html')
138+
->setAttribute('description_html', $chapter->descriptionHtml());
139+
140+
return $chapter;
141+
}
122142
}

0 commit comments

Comments
 (0)