]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/BookshelfController.php
Merge pull request #3591 from BookStackApp/shelf_books_enhancements
[bookstack] / app / Http / Controllers / BookshelfController.php
1 <?php
2
3 namespace BookStack\Http\Controllers;
4
5 use BookStack\Actions\ActivityQueries;
6 use BookStack\Actions\View;
7 use BookStack\Entities\Models\Book;
8 use BookStack\Entities\Repos\BookshelfRepo;
9 use BookStack\Entities\Tools\PermissionsUpdater;
10 use BookStack\Entities\Tools\ShelfContext;
11 use BookStack\Exceptions\ImageUploadException;
12 use BookStack\Exceptions\NotFoundException;
13 use Exception;
14 use Illuminate\Http\Request;
15 use Illuminate\Validation\ValidationException;
16
17 class BookshelfController extends Controller
18 {
19     protected BookshelfRepo $shelfRepo;
20     protected ShelfContext $shelfContext;
21
22     public function __construct(BookshelfRepo $shelfRepo, ShelfContext $shelfContext)
23     {
24         $this->shelfRepo = $shelfRepo;
25         $this->shelfContext = $shelfContext;
26     }
27
28     /**
29      * Display a listing of the book.
30      */
31     public function index()
32     {
33         $view = setting()->getForCurrentUser('bookshelves_view_type');
34         $sort = setting()->getForCurrentUser('bookshelves_sort', 'name');
35         $order = setting()->getForCurrentUser('bookshelves_sort_order', 'asc');
36         $sortOptions = [
37             'name'       => trans('common.sort_name'),
38             'created_at' => trans('common.sort_created_at'),
39             'updated_at' => trans('common.sort_updated_at'),
40         ];
41
42         $shelves = $this->shelfRepo->getAllPaginated(18, $sort, $order);
43         $recents = $this->isSignedIn() ? $this->shelfRepo->getRecentlyViewed(4) : false;
44         $popular = $this->shelfRepo->getPopular(4);
45         $new = $this->shelfRepo->getRecentlyCreated(4);
46
47         $this->shelfContext->clearShelfContext();
48         $this->setPageTitle(trans('entities.shelves'));
49
50         return view('shelves.index', [
51             'shelves'     => $shelves,
52             'recents'     => $recents,
53             'popular'     => $popular,
54             'new'         => $new,
55             'view'        => $view,
56             'sort'        => $sort,
57             'order'       => $order,
58             'sortOptions' => $sortOptions,
59         ]);
60     }
61
62     /**
63      * Show the form for creating a new bookshelf.
64      */
65     public function create()
66     {
67         $this->checkPermission('bookshelf-create-all');
68         $books = Book::visible()->orderBy('name')->get(['name', 'id', 'slug']);
69         $this->setPageTitle(trans('entities.shelves_create'));
70
71         return view('shelves.create', ['books' => $books]);
72     }
73
74     /**
75      * Store a newly created bookshelf in storage.
76      *
77      * @throws ValidationException
78      * @throws ImageUploadException
79      */
80     public function store(Request $request)
81     {
82         $this->checkPermission('bookshelf-create-all');
83         $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'],
88         ]);
89
90         $bookIds = explode(',', $request->get('books', ''));
91         $shelf = $this->shelfRepo->create($validated, $bookIds);
92
93         return redirect($shelf->getUrl());
94     }
95
96     /**
97      * Display the bookshelf of the given slug.
98      *
99      * @throws NotFoundException
100      */
101     public function show(ActivityQueries $activities, string $slug)
102     {
103         $shelf = $this->shelfRepo->getBySlug($slug);
104         $this->checkOwnablePermission('bookshelf-view', $shelf);
105
106         $sort = setting()->getForCurrentUser('shelf_books_sort', 'default');
107         $order = setting()->getForCurrentUser('shelf_books_sort_order', 'asc');
108
109         $sortedVisibleShelfBooks = $shelf->visibleBooks()->get()
110             ->sortBy($sort === 'default' ? 'pivot.order' : $sort, SORT_REGULAR, $order === 'desc')
111             ->values()
112             ->all();
113
114         View::incrementFor($shelf);
115         $this->shelfContext->setShelfContext($shelf->id);
116         $view = setting()->getForCurrentUser('bookshelf_view_type');
117
118         $this->setPageTitle($shelf->getShortName());
119
120         return view('shelves.show', [
121             'shelf'                   => $shelf,
122             'sortedVisibleShelfBooks' => $sortedVisibleShelfBooks,
123             'view'                    => $view,
124             'activity'                => $activities->entityActivity($shelf, 20, 1),
125             'order'                   => $order,
126             'sort'                    => $sort,
127         ]);
128     }
129
130     /**
131      * Show the form for editing the specified bookshelf.
132      */
133     public function edit(string $slug)
134     {
135         $shelf = $this->shelfRepo->getBySlug($slug);
136         $this->checkOwnablePermission('bookshelf-update', $shelf);
137
138         $shelfBookIds = $shelf->books()->get(['id'])->pluck('id');
139         $books = Book::visible()->whereNotIn('id', $shelfBookIds)->orderBy('name')->get(['name', 'id', 'slug']);
140
141         $this->setPageTitle(trans('entities.shelves_edit_named', ['name' => $shelf->getShortName()]));
142
143         return view('shelves.edit', [
144             'shelf' => $shelf,
145             'books' => $books,
146         ]);
147     }
148
149     /**
150      * Update the specified bookshelf in storage.
151      *
152      * @throws ValidationException
153      * @throws ImageUploadException
154      * @throws NotFoundException
155      */
156     public function update(Request $request, string $slug)
157     {
158         $shelf = $this->shelfRepo->getBySlug($slug);
159         $this->checkOwnablePermission('bookshelf-update', $shelf);
160         $validated = $this->validate($request, [
161             'name'        => ['required', 'string', 'max:255'],
162             'description' => ['string', 'max:1000'],
163             'image'       => array_merge(['nullable'], $this->getImageValidationRules()),
164             'tags'        => ['array'],
165         ]);
166
167         if ($request->has('image_reset')) {
168             $validated['image'] = null;
169         } elseif (array_key_exists('image', $validated) && is_null($validated['image'])) {
170             unset($validated['image']);
171         }
172
173         $bookIds = explode(',', $request->get('books', ''));
174         $shelf = $this->shelfRepo->update($shelf, $validated, $bookIds);
175
176         return redirect($shelf->getUrl());
177     }
178
179     /**
180      * Shows the page to confirm deletion.
181      */
182     public function showDelete(string $slug)
183     {
184         $shelf = $this->shelfRepo->getBySlug($slug);
185         $this->checkOwnablePermission('bookshelf-delete', $shelf);
186
187         $this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $shelf->getShortName()]));
188
189         return view('shelves.delete', ['shelf' => $shelf]);
190     }
191
192     /**
193      * Remove the specified bookshelf from storage.
194      *
195      * @throws Exception
196      */
197     public function destroy(string $slug)
198     {
199         $shelf = $this->shelfRepo->getBySlug($slug);
200         $this->checkOwnablePermission('bookshelf-delete', $shelf);
201
202         $this->shelfRepo->destroy($shelf);
203
204         return redirect('/shelves');
205     }
206
207     /**
208      * Show the permissions view.
209      */
210     public function showPermissions(string $slug)
211     {
212         $shelf = $this->shelfRepo->getBySlug($slug);
213         $this->checkOwnablePermission('restrictions-manage', $shelf);
214
215         return view('shelves.permissions', [
216             'shelf' => $shelf,
217         ]);
218     }
219
220     /**
221      * Set the permissions for this bookshelf.
222      */
223     public function permissions(Request $request, PermissionsUpdater $permissionsUpdater, string $slug)
224     {
225         $shelf = $this->shelfRepo->getBySlug($slug);
226         $this->checkOwnablePermission('restrictions-manage', $shelf);
227
228         $permissionsUpdater->updateFromPermissionsForm($shelf, $request);
229
230         $this->showSuccessNotification(trans('entities.shelves_permissions_updated'));
231
232         return redirect($shelf->getUrl());
233     }
234
235     /**
236      * Copy the permissions of a bookshelf to the child books.
237      */
238     public function copyPermissions(string $slug)
239     {
240         $shelf = $this->shelfRepo->getBySlug($slug);
241         $this->checkOwnablePermission('restrictions-manage', $shelf);
242
243         $updateCount = $this->shelfRepo->copyDownPermissions($shelf);
244         $this->showSuccessNotification(trans('entities.shelves_copy_permission_success', ['count' => $updateCount]));
245
246         return redirect($shelf->getUrl());
247     }
248 }