3 namespace BookStack\Entities\Controllers;
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\References\ReferenceFetcher;
15 use BookStack\Util\SimpleListOptions;
17 use Illuminate\Http\Request;
18 use Illuminate\Validation\ValidationException;
20 class BookshelfController extends Controller
22 public function __construct(
23 protected BookshelfRepo $shelfRepo,
24 protected BookshelfQueries $queries,
25 protected BookQueries $bookQueries,
26 protected ShelfContext $shelfContext,
27 protected ReferenceFetcher $referenceFetcher,
32 * Display a listing of bookshelves.
34 public function index(Request $request)
36 $view = setting()->getForCurrentUser('bookshelves_view_type');
37 $listOptions = SimpleListOptions::fromRequest($request, 'bookshelves')->withSortOptions([
38 'name' => trans('common.sort_name'),
39 'created_at' => trans('common.sort_created_at'),
40 'updated_at' => trans('common.sort_updated_at'),
43 $shelves = $this->queries->visibleForListWithCover()
44 ->orderBy($listOptions->getSort(), $listOptions->getOrder())
46 $recents = $this->isSignedIn() ? $this->queries->recentlyViewedForCurrentUser()->get() : false;
47 $popular = $this->queries->popularForList()->get();
48 $new = $this->queries->visibleForList()
49 ->orderBy('created_at', 'desc')
53 $this->shelfContext->clearShelfContext();
54 $this->setPageTitle(trans('entities.shelves'));
56 return view('shelves.index', [
57 'shelves' => $shelves,
58 'recents' => $recents,
59 'popular' => $popular,
62 'listOptions' => $listOptions,
67 * Show the form for creating a new bookshelf.
69 public function create()
71 $this->checkPermission('bookshelf-create-all');
72 $books = $this->bookQueries->visibleForList()->orderBy('name')->get(['name', 'id', 'slug', 'created_at', 'updated_at']);
73 $this->setPageTitle(trans('entities.shelves_create'));
75 return view('shelves.create', ['books' => $books]);
79 * Store a newly created bookshelf in storage.
81 * @throws ValidationException
82 * @throws ImageUploadException
84 public function store(Request $request)
86 $this->checkPermission('bookshelf-create-all');
87 $validated = $this->validate($request, [
88 'name' => ['required', 'string', 'max:255'],
89 'description_html' => ['string', 'max:2000'],
90 'image' => array_merge(['nullable'], $this->getImageValidationRules()),
94 $bookIds = explode(',', $request->get('books', ''));
95 $shelf = $this->shelfRepo->create($validated, $bookIds);
97 return redirect($shelf->getUrl());
101 * Display the bookshelf of the given slug.
103 * @throws NotFoundException
105 public function show(Request $request, ActivityQueries $activities, string $slug)
107 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
108 $this->checkOwnablePermission('bookshelf-view', $shelf);
110 $listOptions = SimpleListOptions::fromRequest($request, 'shelf_books')->withSortOptions([
111 'default' => trans('common.sort_default'),
112 'name' => trans('common.sort_name'),
113 'created_at' => trans('common.sort_created_at'),
114 'updated_at' => trans('common.sort_updated_at'),
117 $sort = $listOptions->getSort();
118 $sortedVisibleShelfBooks = $shelf->visibleBooks()
119 ->reorder($sort === 'default' ? 'order' : $sort, $listOptions->getOrder())
124 View::incrementFor($shelf);
125 $this->shelfContext->setShelfContext($shelf->id);
126 $view = setting()->getForCurrentUser('bookshelf_view_type');
128 $this->setPageTitle($shelf->getShortName());
130 return view('shelves.show', [
132 'sortedVisibleShelfBooks' => $sortedVisibleShelfBooks,
134 'activity' => $activities->entityActivity($shelf, 20, 1),
135 'listOptions' => $listOptions,
136 'referenceCount' => $this->referenceFetcher->getReferenceCountToEntity($shelf),
141 * Show the form for editing the specified bookshelf.
143 public function edit(string $slug)
145 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
146 $this->checkOwnablePermission('bookshelf-update', $shelf);
148 $shelfBookIds = $shelf->books()->get(['id'])->pluck('id');
149 $books = $this->bookQueries->visibleForList()
150 ->whereNotIn('id', $shelfBookIds)
152 ->get(['name', 'id', 'slug', 'created_at', 'updated_at']);
154 $this->setPageTitle(trans('entities.shelves_edit_named', ['name' => $shelf->getShortName()]));
156 return view('shelves.edit', [
163 * Update the specified bookshelf in storage.
165 * @throws ValidationException
166 * @throws ImageUploadException
167 * @throws NotFoundException
169 public function update(Request $request, string $slug)
171 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
172 $this->checkOwnablePermission('bookshelf-update', $shelf);
173 $validated = $this->validate($request, [
174 'name' => ['required', 'string', 'max:255'],
175 'description_html' => ['string', 'max:2000'],
176 'image' => array_merge(['nullable'], $this->getImageValidationRules()),
180 if ($request->has('image_reset')) {
181 $validated['image'] = null;
182 } elseif (array_key_exists('image', $validated) && is_null($validated['image'])) {
183 unset($validated['image']);
186 $bookIds = explode(',', $request->get('books', ''));
187 $shelf = $this->shelfRepo->update($shelf, $validated, $bookIds);
189 return redirect($shelf->getUrl());
193 * Shows the page to confirm deletion.
195 public function showDelete(string $slug)
197 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
198 $this->checkOwnablePermission('bookshelf-delete', $shelf);
200 $this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $shelf->getShortName()]));
202 return view('shelves.delete', ['shelf' => $shelf]);
206 * Remove the specified bookshelf from storage.
210 public function destroy(string $slug)
212 $shelf = $this->queries->findVisibleBySlugOrFail($slug);
213 $this->checkOwnablePermission('bookshelf-delete', $shelf);
215 $this->shelfRepo->destroy($shelf);
217 return redirect('/shelves');