]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/PageController.php
Implemented database structure and inital interfaces for entity restrictions
[bookstack] / app / Http / Controllers / PageController.php
1 <?php namespace BookStack\Http\Controllers;
2
3 use Activity;
4 use BookStack\Repos\UserRepo;
5 use BookStack\Services\ExportService;
6 use Illuminate\Http\Request;
7 use BookStack\Http\Requests;
8 use BookStack\Repos\BookRepo;
9 use BookStack\Repos\ChapterRepo;
10 use BookStack\Repos\PageRepo;
11 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
12 use Views;
13
14 class PageController extends Controller
15 {
16
17     protected $pageRepo;
18     protected $bookRepo;
19     protected $chapterRepo;
20     protected $exportService;
21     protected $userRepo;
22
23     /**
24      * PageController constructor.
25      * @param PageRepo $pageRepo
26      * @param BookRepo $bookRepo
27      * @param ChapterRepo $chapterRepo
28      * @param ExportService $exportService
29      * @param UserRepo $userRepo
30      */
31     public function __construct(PageRepo $pageRepo, BookRepo $bookRepo, ChapterRepo $chapterRepo, ExportService $exportService, UserRepo $userRepo)
32     {
33         $this->pageRepo = $pageRepo;
34         $this->bookRepo = $bookRepo;
35         $this->chapterRepo = $chapterRepo;
36         $this->exportService = $exportService;
37         $this->userRepo = $userRepo;
38         parent::__construct();
39     }
40
41     /**
42      * Show the form for creating a new page.
43      * @param      $bookSlug
44      * @param bool $chapterSlug
45      * @return Response
46      * @internal param bool $pageSlug
47      */
48     public function create($bookSlug, $chapterSlug = false)
49     {
50         $book = $this->bookRepo->getBySlug($bookSlug);
51         $chapter = $chapterSlug ? $this->chapterRepo->getBySlug($chapterSlug, $book->id) : false;
52         $parent = $chapter ? $chapter : $book;
53         $this->checkOwnablePermission('page-create', $parent);
54         $this->setPageTitle('Create New Page');
55         return view('pages/create', ['book' => $book, 'chapter' => $chapter]);
56     }
57
58     /**
59      * Store a newly created page in storage.
60      * @param  Request $request
61      * @param          $bookSlug
62      * @return Response
63      */
64     public function store(Request $request, $bookSlug)
65     {
66         $this->validate($request, [
67             'name'   => 'required|string|max:255'
68         ]);
69
70         $input = $request->all();
71         $book = $this->bookRepo->getBySlug($bookSlug);
72         $chapterId = ($request->has('chapter') && $this->chapterRepo->idExists($request->get('chapter'))) ? $request->get('chapter') : null;
73         $parent = $chapterId !== null ? $this->chapterRepo->getById($chapterId) : $book;
74         $this->checkOwnablePermission('page-create', $parent);
75         $input['priority'] = $this->bookRepo->getNewPriority($book);
76
77         $page = $this->pageRepo->saveNew($input, $book, $chapterId);
78
79         Activity::add($page, 'page_create', $book->id);
80         return redirect($page->getUrl());
81     }
82
83     /**
84      * Display the specified page.
85      * If the page is not found via the slug the
86      * revisions are searched for a match.
87      * @param $bookSlug
88      * @param $pageSlug
89      * @return Response
90      */
91     public function show($bookSlug, $pageSlug)
92     {
93         $book = $this->bookRepo->getBySlug($bookSlug);
94
95         try {
96             $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
97         } catch (NotFoundHttpException $e) {
98             $page = $this->pageRepo->findPageUsingOldSlug($pageSlug, $bookSlug);
99             if ($page === null) abort(404);
100             return redirect($page->getUrl());
101         }
102
103         $sidebarTree = $this->bookRepo->getChildren($book);
104         Views::add($page);
105         $this->setPageTitle($page->getShortName());
106         return view('pages/show', ['page' => $page, 'book' => $book, 'current' => $page, 'sidebarTree' => $sidebarTree]);
107     }
108
109     /**
110      * Show the form for editing the specified page.
111      * @param $bookSlug
112      * @param $pageSlug
113      * @return Response
114      */
115     public function edit($bookSlug, $pageSlug)
116     {
117         $book = $this->bookRepo->getBySlug($bookSlug);
118         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
119         $this->checkOwnablePermission('page-update', $page);
120         $this->setPageTitle('Editing Page ' . $page->getShortName());
121         return view('pages/edit', ['page' => $page, 'book' => $book, 'current' => $page]);
122     }
123
124     /**
125      * Update the specified page in storage.
126      * @param  Request $request
127      * @param          $bookSlug
128      * @param          $pageSlug
129      * @return Response
130      */
131     public function update(Request $request, $bookSlug, $pageSlug)
132     {
133         $this->validate($request, [
134             'name'   => 'required|string|max:255'
135         ]);
136         $book = $this->bookRepo->getBySlug($bookSlug);
137         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
138         $this->checkOwnablePermission('page-update', $page);
139         $this->pageRepo->updatePage($page, $book->id, $request->all());
140         Activity::add($page, 'page_update', $book->id);
141         return redirect($page->getUrl());
142     }
143
144     /**
145      * Redirect from a special link url which
146      * uses the page id rather than the name.
147      * @param $pageId
148      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
149      */
150     public function redirectFromLink($pageId)
151     {
152         $page = $this->pageRepo->getById($pageId);
153         return redirect($page->getUrl());
154     }
155
156     /**
157      * Show the deletion page for the specified page.
158      * @param $bookSlug
159      * @param $pageSlug
160      * @return \Illuminate\View\View
161      */
162     public function showDelete($bookSlug, $pageSlug)
163     {
164         $book = $this->bookRepo->getBySlug($bookSlug);
165         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
166         $this->checkOwnablePermission('page-delete', $page);
167         $this->setPageTitle('Delete Page ' . $page->getShortName());
168         return view('pages/delete', ['book' => $book, 'page' => $page, 'current' => $page]);
169     }
170
171     /**
172      * Remove the specified page from storage.
173      *
174      * @param $bookSlug
175      * @param $pageSlug
176      * @return Response
177      * @internal param int $id
178      */
179     public function destroy($bookSlug, $pageSlug)
180     {
181         $book = $this->bookRepo->getBySlug($bookSlug);
182         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
183         $this->checkOwnablePermission('page-delete', $page);
184         Activity::addMessage('page_delete', $book->id, $page->name);
185         $this->pageRepo->destroy($page);
186         return redirect($book->getUrl());
187     }
188
189     /**
190      * Shows the last revisions for this page.
191      * @param $bookSlug
192      * @param $pageSlug
193      * @return \Illuminate\View\View
194      */
195     public function showRevisions($bookSlug, $pageSlug)
196     {
197         $book = $this->bookRepo->getBySlug($bookSlug);
198         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
199         $this->setPageTitle('Revisions For ' . $page->getShortName());
200         return view('pages/revisions', ['page' => $page, 'book' => $book, 'current' => $page]);
201     }
202
203     /**
204      * Shows a preview of a single revision
205      * @param $bookSlug
206      * @param $pageSlug
207      * @param $revisionId
208      * @return \Illuminate\View\View
209      */
210     public function showRevision($bookSlug, $pageSlug, $revisionId)
211     {
212         $book = $this->bookRepo->getBySlug($bookSlug);
213         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
214         $revision = $this->pageRepo->getRevisionById($revisionId);
215         $page->fill($revision->toArray());
216         $this->setPageTitle('Page Revision For ' . $page->getShortName());
217         return view('pages/revision', ['page' => $page, 'book' => $book]);
218     }
219
220     /**
221      * Restores a page using the content of the specified revision.
222      * @param $bookSlug
223      * @param $pageSlug
224      * @param $revisionId
225      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
226      */
227     public function restoreRevision($bookSlug, $pageSlug, $revisionId)
228     {
229         $book = $this->bookRepo->getBySlug($bookSlug);
230         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
231         $this->checkOwnablePermission('page-update', $page);
232         $page = $this->pageRepo->restoreRevision($page, $book, $revisionId);
233         Activity::add($page, 'page_restore', $book->id);
234         return redirect($page->getUrl());
235     }
236
237     /**
238      * Exports a page to pdf format using barryvdh/laravel-dompdf wrapper.
239      * https://github.com/barryvdh/laravel-dompdf
240      * @param $bookSlug
241      * @param $pageSlug
242      * @return \Illuminate\Http\Response
243      */
244     public function exportPdf($bookSlug, $pageSlug)
245     {
246         $book = $this->bookRepo->getBySlug($bookSlug);
247         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
248         $pdfContent = $this->exportService->pageToPdf($page);
249         return response()->make($pdfContent, 200, [
250             'Content-Type' => 'application/octet-stream',
251             'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.pdf'
252         ]);
253     }
254
255     /**
256      * Export a page to a self-contained HTML file.
257      * @param $bookSlug
258      * @param $pageSlug
259      * @return \Illuminate\Http\Response
260      */
261     public function exportHtml($bookSlug, $pageSlug)
262     {
263         $book = $this->bookRepo->getBySlug($bookSlug);
264         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
265         $containedHtml = $this->exportService->pageToContainedHtml($page);
266         return response()->make($containedHtml, 200, [
267             'Content-Type' => 'application/octet-stream',
268             'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.html'
269         ]);
270     }
271
272     /**
273      * Export a page to a simple plaintext .txt file.
274      * @param $bookSlug
275      * @param $pageSlug
276      * @return \Illuminate\Http\Response
277      */
278     public function exportPlainText($bookSlug, $pageSlug)
279     {
280         $book = $this->bookRepo->getBySlug($bookSlug);
281         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
282         $containedHtml = $this->exportService->pageToPlainText($page);
283         return response()->make($containedHtml, 200, [
284             'Content-Type' => 'application/octet-stream',
285             'Content-Disposition' => 'attachment; filename="'.$pageSlug.'.txt'
286         ]);
287     }
288
289     /**
290      * Show a listing of recently created pages
291      * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
292      */
293     public function showRecentlyCreated()
294     {
295         $pages = $this->pageRepo->getRecentlyCreatedPaginated(20);
296         return view('pages/detailed-listing', [
297             'title' => 'Recently Created Pages',
298             'pages' => $pages
299         ]);
300     }
301
302     /**
303      * Show a listing of recently created pages
304      * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
305      */
306     public function showRecentlyUpdated()
307     {
308         $pages = $this->pageRepo->getRecentlyUpdatedPaginated(20);
309         return view('pages/detailed-listing', [
310             'title' => 'Recently Updated Pages',
311             'pages' => $pages
312         ]);
313     }
314
315     /**
316      * Show the Restrictions view.
317      * @param $bookSlug
318      * @param $pageSlug
319      * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
320      */
321     public function showRestrict($bookSlug, $pageSlug)
322     {
323         $book = $this->bookRepo->getBySlug($bookSlug);
324         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
325         $this->checkOwnablePermission('restrictions-manage', $page);
326         $roles = $this->userRepo->getRestrictableRoles();
327         return view('pages/restrictions', [
328             'page' => $page,
329             'roles' => $roles
330         ]);
331     }
332
333     /**
334      * Set the restrictions for this page.
335      * @param $bookSlug
336      * @param $pageSlug
337      * @param Request $request
338      * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
339      */
340     public function restrict($bookSlug, $pageSlug, Request $request)
341     {
342         $book = $this->bookRepo->getBySlug($bookSlug);
343         $page = $this->pageRepo->getBySlug($pageSlug, $book->id);
344         $this->checkOwnablePermission('restrictions-manage', $page);
345         $this->pageRepo->updateRestrictionsFromRequest($request, $page);
346         session()->flash('success', 'Page Restrictions Updated');
347         return redirect($page->getUrl());
348     }
349
350 }