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