]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/BookController.php
Merge pull request #3 from BookStackApp/master
[bookstack] / app / Http / Controllers / BookController.php
1 <?php namespace BookStack\Http\Controllers;
2
3 use Activity;
4 use BookStack\Repos\EntityRepo;
5 use BookStack\Repos\UserRepo;
6 use Illuminate\Http\Request;
7 use Illuminate\Http\Response;
8 use Views;
9
10 class BookController extends Controller
11 {
12
13     protected $entityRepo;
14     protected $userRepo;
15
16     /**
17      * BookController constructor.
18      * @param EntityRepo $entityRepo
19      * @param UserRepo $userRepo
20      */
21     public function __construct(EntityRepo $entityRepo, UserRepo $userRepo)
22     {
23         $this->entityRepo = $entityRepo;
24         $this->userRepo = $userRepo;
25         parent::__construct();
26     }
27
28     /**
29      * Display a listing of the book.
30      * @return Response
31      */
32     public function index()
33     {
34         $books = $this->entityRepo->getAllPaginated('book', 10);
35         $recents = $this->signedIn ? $this->entityRepo->getRecentlyViewed('book', 4, 0) : false;
36         $popular = $this->entityRepo->getPopular('book', 4, 0);
37         $this->setPageTitle('Books');
38         return view('books/index', ['books' => $books, 'recents' => $recents, 'popular' => $popular]);
39     }
40
41     /**
42      * Show the form for creating a new book.
43      * @return Response
44      */
45     public function create()
46     {
47         $this->checkPermission('book-create-all');
48         $this->setPageTitle(trans('entities.books_create'));
49         return view('books/create');
50     }
51
52     /**
53      * Store a newly created book in storage.
54      *
55      * @param  Request $request
56      * @return Response
57      */
58     public function store(Request $request)
59     {
60         $this->checkPermission('book-create-all');
61         $this->validate($request, [
62             'name' => 'required|string|max:255',
63             'description' => 'string|max:1000'
64         ]);
65         $book = $this->entityRepo->createFromInput('book', $request->all());
66         Activity::add($book, 'book_create', $book->id);
67         return redirect($book->getUrl());
68     }
69
70     /**
71      * Display the specified book.
72      * @param $slug
73      * @return Response
74      */
75     public function show($slug)
76     {
77         $book = $this->entityRepo->getBySlug('book', $slug);
78         $this->checkOwnablePermission('book-view', $book);
79         $bookChildren = $this->entityRepo->getBookChildren($book);
80         Views::add($book);
81         $this->setPageTitle($book->getShortName());
82         return view('books/show', ['book' => $book, 'current' => $book, 'bookChildren' => $bookChildren]);
83     }
84
85     /**
86      * Show the form for editing the specified book.
87      * @param $slug
88      * @return Response
89      */
90     public function edit($slug)
91     {
92         $book = $this->entityRepo->getBySlug('book', $slug);
93         $this->checkOwnablePermission('book-update', $book);
94         $this->setPageTitle(trans('entities.books_edit_named',['bookName'=>$book->getShortName()]));
95         return view('books/edit', ['book' => $book, 'current' => $book]);
96     }
97
98     /**
99      * Update the specified book in storage.
100      * @param  Request $request
101      * @param          $slug
102      * @return Response
103      */
104     public function update(Request $request, $slug)
105     {
106         $book = $this->entityRepo->getBySlug('book', $slug);
107         $this->checkOwnablePermission('book-update', $book);
108         $this->validate($request, [
109             'name' => 'required|string|max:255',
110             'description' => 'string|max:1000'
111         ]);
112         $book = $this->entityRepo->updateFromInput('book', $book, $request->all());
113         Activity::add($book, 'book_update', $book->id);
114         return redirect($book->getUrl());
115     }
116
117     /**
118      * Shows the page to confirm deletion
119      * @param $bookSlug
120      * @return \Illuminate\View\View
121      */
122     public function showDelete($bookSlug)
123     {
124         $book = $this->entityRepo->getBySlug('book', $bookSlug);
125         $this->checkOwnablePermission('book-delete', $book);
126         $this->setPageTitle(trans('entities.books_delete_named', ['bookName'=>$book->getShortName()]));
127         return view('books/delete', ['book' => $book, 'current' => $book]);
128     }
129
130     /**
131      * Shows the view which allows pages to be re-ordered and sorted.
132      * @param string $bookSlug
133      * @return \Illuminate\View\View
134      */
135     public function sort($bookSlug)
136     {
137         $book = $this->entityRepo->getBySlug('book', $bookSlug);
138         $this->checkOwnablePermission('book-update', $book);
139         $bookChildren = $this->entityRepo->getBookChildren($book, true);
140         $books = $this->entityRepo->getAll('book', false);
141         $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()]));
142         return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]);
143     }
144
145     /**
146      * Shows the sort box for a single book.
147      * Used via AJAX when loading in extra books to a sort.
148      * @param $bookSlug
149      * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
150      */
151     public function getSortItem($bookSlug)
152     {
153         $book = $this->entityRepo->getBySlug('book', $bookSlug);
154         $bookChildren = $this->entityRepo->getBookChildren($book);
155         return view('books/sort-box', ['book' => $book, 'bookChildren' => $bookChildren]);
156     }
157
158     /**
159      * Saves an array of sort mapping to pages and chapters.
160      * @param  string $bookSlug
161      * @param Request $request
162      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
163      */
164     public function saveSort($bookSlug, Request $request)
165     {
166         $book = $this->entityRepo->getBySlug('book', $bookSlug);
167         $this->checkOwnablePermission('book-update', $book);
168
169         // Return if no map sent
170         if (!$request->has('sort-tree')) {
171             return redirect($book->getUrl());
172         }
173
174         // Sort pages and chapters
175         $sortedBooks = [];
176         $updatedModels = collect();
177         $sortMap = json_decode($request->get('sort-tree'));
178         $defaultBookId = $book->id;
179
180         // Loop through contents of provided map and update entities accordingly
181         foreach ($sortMap as $bookChild) {
182             $priority = $bookChild->sort;
183             $id = intval($bookChild->id);
184             $isPage = $bookChild->type == 'page';
185             $bookId = $this->entityRepo->exists('book', $bookChild->book) ? intval($bookChild->book) : $defaultBookId;
186             $chapterId = ($isPage && $bookChild->parentChapter === false) ? 0 : intval($bookChild->parentChapter);
187             $model = $this->entityRepo->getById($isPage?'page':'chapter', $id);
188
189             // Update models only if there's a change in parent chain or ordering.
190             if ($model->priority !== $priority || $model->book_id !== $bookId || ($isPage && $model->chapter_id !== $chapterId)) {
191                 $this->entityRepo->changeBook($isPage?'page':'chapter', $bookId, $model);
192                 $model->priority = $priority;
193                 if ($isPage) $model->chapter_id = $chapterId;
194                 $model->save();
195                 $updatedModels->push($model);
196             }
197
198             // Store involved books to be sorted later
199             if (!in_array($bookId, $sortedBooks)) {
200                 $sortedBooks[] = $bookId;
201             }
202         }
203
204         // Add activity for books
205         foreach ($sortedBooks as $bookId) {
206             $updatedBook = $this->entityRepo->getById('book', $bookId);
207             Activity::add($updatedBook, 'book_sort', $updatedBook->id);
208         }
209
210         // Update permissions on changed models
211         $this->entityRepo->buildJointPermissions($updatedModels);
212
213         return redirect($book->getUrl());
214     }
215
216     /**
217      * Remove the specified book from storage.
218      * @param $bookSlug
219      * @return Response
220      */
221     public function destroy($bookSlug)
222     {
223         $book = $this->entityRepo->getBySlug('book', $bookSlug);
224         $this->checkOwnablePermission('book-delete', $book);
225         Activity::addMessage('book_delete', 0, $book->name);
226         $this->entityRepo->destroyBook($book);
227         return redirect('/books');
228     }
229
230     /**
231      * Show the Restrictions view.
232      * @param $bookSlug
233      * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
234      */
235     public function showRestrict($bookSlug)
236     {
237         $book = $this->entityRepo->getBySlug('book', $bookSlug);
238         $this->checkOwnablePermission('restrictions-manage', $book);
239         $roles = $this->userRepo->getRestrictableRoles();
240         return view('books/restrictions', [
241             'book' => $book,
242             'roles' => $roles
243         ]);
244     }
245
246     /**
247      * Set the restrictions for this book.
248      * @param $bookSlug
249      * @param $bookSlug
250      * @param Request $request
251      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
252      */
253     public function restrict($bookSlug, Request $request)
254     {
255         $book = $this->entityRepo->getBySlug('book', $bookSlug);
256         $this->checkOwnablePermission('restrictions-manage', $book);
257         $this->entityRepo->updateEntityPermissionsFromRequest($request, $book);
258         session()->flash('success', trans('entities.books_permissions_updated'));
259         return redirect($book->getUrl());
260     }
261 }