]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/PageRevisionController.php
Cleaned testing service provider usage
[bookstack] / app / Http / Controllers / PageRevisionController.php
1 <?php
2
3 namespace BookStack\Http\Controllers;
4
5 use BookStack\Actions\ActivityType;
6 use BookStack\Entities\Repos\PageRepo;
7 use BookStack\Entities\Tools\PageContent;
8 use BookStack\Exceptions\NotFoundException;
9 use BookStack\Facades\Activity;
10 use Ssddanbrown\HtmlDiff\Diff;
11
12 class PageRevisionController extends Controller
13 {
14     protected PageRepo $pageRepo;
15
16     public function __construct(PageRepo $pageRepo)
17     {
18         $this->pageRepo = $pageRepo;
19     }
20
21     /**
22      * Shows the last revisions for this page.
23      *
24      * @throws NotFoundException
25      */
26     public function index(string $bookSlug, string $pageSlug)
27     {
28         $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
29         $revisions = $page->revisions()->select([
30             'id', 'page_id', 'name', 'created_at', 'created_by', 'updated_at',
31             'type', 'revision_number', 'summary',
32         ])
33             ->selectRaw("IF(markdown = '', false, true) as is_markdown")
34             ->with(['page.book', 'createdBy'])
35             ->get();
36
37         $this->setPageTitle(trans('entities.pages_revisions_named', ['pageName' => $page->getShortName()]));
38
39         return view('pages.revisions', [
40             'revisions' => $revisions,
41             'page'      => $page,
42         ]);
43     }
44
45     /**
46      * Shows a preview of a single revision.
47      *
48      * @throws NotFoundException
49      */
50     public function show(string $bookSlug, string $pageSlug, int $revisionId)
51     {
52         $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
53         $revision = $page->revisions()->where('id', '=', $revisionId)->first();
54         if ($revision === null) {
55             throw new NotFoundException();
56         }
57
58         $page->fill($revision->toArray());
59         // TODO - Refactor PageContent so we don't need to juggle this
60         $page->html = $revision->html;
61         $page->html = (new PageContent($page))->render();
62
63         $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
64
65         return view('pages.revision', [
66             'page'     => $page,
67             'book'     => $page->book,
68             'diff'     => null,
69             'revision' => $revision,
70         ]);
71     }
72
73     /**
74      * Shows the changes of a single revision.
75      *
76      * @throws NotFoundException
77      */
78     public function changes(string $bookSlug, string $pageSlug, int $revisionId)
79     {
80         $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
81         $revision = $page->revisions()->where('id', '=', $revisionId)->first();
82         if ($revision === null) {
83             throw new NotFoundException();
84         }
85
86         $prev = $revision->getPrevious();
87         $prevContent = $prev->html ?? '';
88         $diff = Diff::excecute($prevContent, $revision->html);
89
90         $page->fill($revision->toArray());
91         // TODO - Refactor PageContent so we don't need to juggle this
92         $page->html = $revision->html;
93         $page->html = (new PageContent($page))->render();
94         $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
95
96         return view('pages.revision', [
97             'page'     => $page,
98             'book'     => $page->book,
99             'diff'     => $diff,
100             'revision' => $revision,
101         ]);
102     }
103
104     /**
105      * Restores a page using the content of the specified revision.
106      *
107      * @throws NotFoundException
108      */
109     public function restore(string $bookSlug, string $pageSlug, int $revisionId)
110     {
111         $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
112         $this->checkOwnablePermission('page-update', $page);
113
114         $page = $this->pageRepo->restoreRevision($page, $revisionId);
115
116         return redirect($page->getUrl());
117     }
118
119     /**
120      * Deletes a revision using the id of the specified revision.
121      *
122      * @throws NotFoundException
123      */
124     public function destroy(string $bookSlug, string $pageSlug, int $revId)
125     {
126         $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
127         $this->checkOwnablePermission('page-delete', $page);
128
129         $revision = $page->revisions()->where('id', '=', $revId)->first();
130         if ($revision === null) {
131             throw new NotFoundException("Revision #{$revId} not found");
132         }
133
134         // Check if it's the latest revision, cannot delete the latest revision.
135         if (intval($page->currentRevision->id ?? null) === intval($revId)) {
136             $this->showErrorNotification(trans('entities.revision_cannot_delete_latest'));
137
138             return redirect($page->getUrl('/revisions'));
139         }
140
141         $revision->delete();
142         Activity::add(ActivityType::REVISION_DELETE, $revision);
143         $this->showSuccessNotification(trans('entities.revision_delete_success'));
144
145         return redirect($page->getUrl('/revisions'));
146     }
147 }