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