]> BookStack Code Mirror - bookstack/blob - app/Entities/Controllers/BookshelfController.php
bc3fc2a6ff00efeb27d12103363a8781147f30bc
[bookstack] / app / Entities / Controllers / BookshelfController.php
1 <?php
2
3 namespace BookStack\Entities\Controllers;
4
5 use BookStack\Activity\ActivityQueries;
6 use BookStack\Activity\Models\View;
7 use BookStack\Entities\Models\Book;
8 use BookStack\Entities\Queries\BookshelfQueries;
9 use BookStack\Entities\Repos\BookshelfRepo;
10 use BookStack\Entities\Tools\ShelfContext;
11 use BookStack\Exceptions\ImageUploadException;
12 use BookStack\Exceptions\NotFoundException;
13 use BookStack\Http\Controller;
14 use BookStack\References\ReferenceFetcher;
15 use BookStack\Util\SimpleListOptions;
16 use Exception;
17 use Illuminate\Http\Request;
18 use Illuminate\Validation\ValidationException;
19
20 class BookshelfController extends Controller
21 {
22     public function __construct(
23         protected BookshelfRepo $shelfRepo,
24         protected BookshelfQueries $queries,
25         protected ShelfContext $shelfContext,
26         protected ReferenceFetcher $referenceFetcher,
27     ) {
28     }
29
30     /**
31      * Display a listing of bookshelves.
32      */
33     public function index(Request $request)
34     {
35         $view = setting()->getForCurrentUser('bookshelves_view_type');
36         $listOptions = SimpleListOptions::fromRequest($request, 'bookshelves')->withSortOptions([
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->queries->visibleForListWithCover()
43             ->orderBy($listOptions->getSort(), $listOptions->getOrder())
44             ->paginate(18);
45         $recents = $this->isSignedIn() ? $this->queries->recentlyViewedForCurrentUser()->get() : false;
46         $popular = $this->queries->popularForList()->get();
47         $new = $this->queries->visibleForList()
48             ->orderBy('created_at', 'desc')
49             ->take(4)
50             ->get();
51
52         $this->shelfContext->clearShelfContext();
53         $this->setPageTitle(trans('entities.shelves'));
54
55         return view('shelves.index', [
56             'shelves'     => $shelves,
57             'recents'     => $recents,
58             'popular'     => $popular,
59             'new'         => $new,
60             'view'        => $view,
61             'listOptions' => $listOptions,
62         ]);
63     }
64
65     /**
66      * Show the form for creating a new bookshelf.
67      */
68     public function create()
69     {
70         $this->checkPermission('bookshelf-create-all');
71         $books = Book::visible()->orderBy('name')->get(['name', 'id', 'slug', 'created_at', 'updated_at']);
72         $this->setPageTitle(trans('entities.shelves_create'));
73
74         return view('shelves.create', ['books' => $books]);
75     }
76
77     /**
78      * Store a newly created bookshelf in storage.
79      *
80      * @throws ValidationException
81      * @throws ImageUploadException
82      */
83     public function store(Request $request)
84     {
85         $this->checkPermission('bookshelf-create-all');
86         $validated = $this->validate($request, [
87             'name'             => ['required', 'string', 'max:255'],
88             'description_html' => ['string', 'max:2000'],
89             'image'            => array_merge(['nullable'], $this->getImageValidationRules()),
90             'tags'             => ['array'],
91         ]);
92
93         $bookIds = explode(',', $request->get('books', ''));
94         $shelf = $this->shelfRepo->create($validated, $bookIds);
95
96         return redirect($shelf->getUrl());
97     }
98
99     /**
100      * Display the bookshelf of the given slug.
101      *
102      * @throws NotFoundException
103      */
104     public function show(Request $request, ActivityQueries $activities, string $slug)
105     {
106         $shelf = $this->queries->findVisibleBySlug($slug);
107         $this->checkOwnablePermission('bookshelf-view', $shelf);
108
109         $listOptions = SimpleListOptions::fromRequest($request, 'shelf_books')->withSortOptions([
110             'default' => trans('common.sort_default'),
111             'name' => trans('common.sort_name'),
112             'created_at' => trans('common.sort_created_at'),
113             'updated_at' => trans('common.sort_updated_at'),
114         ]);
115
116         $sort = $listOptions->getSort();
117         $sortedVisibleShelfBooks = $shelf->visibleBooks()
118             ->reorder($sort === 'default' ? 'order' : $sort, $listOptions->getOrder())
119             ->get()
120             ->values()
121             ->all();
122
123         View::incrementFor($shelf);
124         $this->shelfContext->setShelfContext($shelf->id);
125         $view = setting()->getForCurrentUser('bookshelf_view_type');
126
127         $this->setPageTitle($shelf->getShortName());
128
129         return view('shelves.show', [
130             'shelf'                   => $shelf,
131             'sortedVisibleShelfBooks' => $sortedVisibleShelfBooks,
132             'view'                    => $view,
133             'activity'                => $activities->entityActivity($shelf, 20, 1),
134             'listOptions'             => $listOptions,
135             'referenceCount'          => $this->referenceFetcher->getReferenceCountToEntity($shelf),
136         ]);
137     }
138
139     /**
140      * Show the form for editing the specified bookshelf.
141      */
142     public function edit(string $slug)
143     {
144         $shelf = $this->queries->findVisibleBySlug($slug);
145         $this->checkOwnablePermission('bookshelf-update', $shelf);
146
147         $shelfBookIds = $shelf->books()->get(['id'])->pluck('id');
148         $books = Book::visible()->whereNotIn('id', $shelfBookIds)->orderBy('name')->get(['name', 'id', 'slug', 'created_at', 'updated_at']);
149
150         $this->setPageTitle(trans('entities.shelves_edit_named', ['name' => $shelf->getShortName()]));
151
152         return view('shelves.edit', [
153             'shelf' => $shelf,
154             'books' => $books,
155         ]);
156     }
157
158     /**
159      * Update the specified bookshelf in storage.
160      *
161      * @throws ValidationException
162      * @throws ImageUploadException
163      * @throws NotFoundException
164      */
165     public function update(Request $request, string $slug)
166     {
167         $shelf = $this->queries->findVisibleBySlug($slug);
168         $this->checkOwnablePermission('bookshelf-update', $shelf);
169         $validated = $this->validate($request, [
170             'name'             => ['required', 'string', 'max:255'],
171             'description_html' => ['string', 'max:2000'],
172             'image'            => array_merge(['nullable'], $this->getImageValidationRules()),
173             'tags'             => ['array'],
174         ]);
175
176         if ($request->has('image_reset')) {
177             $validated['image'] = null;
178         } elseif (array_key_exists('image', $validated) && is_null($validated['image'])) {
179             unset($validated['image']);
180         }
181
182         $bookIds = explode(',', $request->get('books', ''));
183         $shelf = $this->shelfRepo->update($shelf, $validated, $bookIds);
184
185         return redirect($shelf->getUrl());
186     }
187
188     /**
189      * Shows the page to confirm deletion.
190      */
191     public function showDelete(string $slug)
192     {
193         $shelf = $this->queries->findVisibleBySlug($slug);
194         $this->checkOwnablePermission('bookshelf-delete', $shelf);
195
196         $this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $shelf->getShortName()]));
197
198         return view('shelves.delete', ['shelf' => $shelf]);
199     }
200
201     /**
202      * Remove the specified bookshelf from storage.
203      *
204      * @throws Exception
205      */
206     public function destroy(string $slug)
207     {
208         $shelf = $this->queries->findVisibleBySlug($slug);
209         $this->checkOwnablePermission('bookshelf-delete', $shelf);
210
211         $this->shelfRepo->destroy($shelf);
212
213         return redirect('/shelves');
214     }
215 }