3 namespace BookStack\Http\Controllers;
5 use BookStack\Actions\ActivityType;
6 use BookStack\Entities\Models\PageRevision;
7 use BookStack\Entities\Repos\PageRepo;
8 use BookStack\Entities\Tools\PageContent;
9 use BookStack\Exceptions\NotFoundException;
10 use BookStack\Facades\Activity;
11 use Ssddanbrown\HtmlDiff\Diff;
13 class PageRevisionController extends Controller
15 protected PageRepo $pageRepo;
17 public function __construct(PageRepo $pageRepo)
19 $this->pageRepo = $pageRepo;
23 * Shows the last revisions for this page.
25 * @throws NotFoundException
27 public function index(string $bookSlug, string $pageSlug)
29 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
30 $revisions = $page->revisions()->select([
31 'id', 'page_id', 'name', 'created_at', 'created_by', 'updated_at',
32 'type', 'revision_number', 'summary',
34 ->selectRaw("IF(markdown = '', false, true) as is_markdown")
35 ->with(['page.book', 'createdBy'])
38 $this->setPageTitle(trans('entities.pages_revisions_named', ['pageName' => $page->getShortName()]));
40 return view('pages.revisions', [
41 'revisions' => $revisions,
47 * Shows a preview of a single revision.
49 * @throws NotFoundException
51 public function show(string $bookSlug, string $pageSlug, int $revisionId)
53 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
54 /** @var ?PageRevision $revision */
55 $revision = $page->revisions()->where('id', '=', $revisionId)->first();
56 if ($revision === null) {
57 throw new NotFoundException();
60 $page->fill($revision->toArray());
61 // TODO - Refactor PageContent so we don't need to juggle this
62 $page->html = $revision->html;
63 $page->html = (new PageContent($page))->render();
65 $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
67 return view('pages.revision', [
69 'book' => $page->book,
71 'revision' => $revision,
76 * Shows the changes of a single revision.
78 * @throws NotFoundException
80 public function changes(string $bookSlug, string $pageSlug, int $revisionId)
82 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
83 /** @var ?PageRevision $revision */
84 $revision = $page->revisions()->where('id', '=', $revisionId)->first();
85 if ($revision === null) {
86 throw new NotFoundException();
89 $prev = $revision->getPrevious();
90 $prevContent = $prev->html ?? '';
91 $diff = Diff::excecute($prevContent, $revision->html);
93 $page->fill($revision->toArray());
94 // TODO - Refactor PageContent so we don't need to juggle this
95 $page->html = $revision->html;
96 $page->html = (new PageContent($page))->render();
97 $this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
99 return view('pages.revision', [
101 'book' => $page->book,
103 'revision' => $revision,
108 * Restores a page using the content of the specified revision.
110 * @throws NotFoundException
112 public function restore(string $bookSlug, string $pageSlug, int $revisionId)
114 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
115 $this->checkOwnablePermission('page-update', $page);
117 $page = $this->pageRepo->restoreRevision($page, $revisionId);
119 return redirect($page->getUrl());
123 * Deletes a revision using the id of the specified revision.
125 * @throws NotFoundException
127 public function destroy(string $bookSlug, string $pageSlug, int $revId)
129 $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
130 $this->checkOwnablePermission('page-delete', $page);
132 $revision = $page->revisions()->where('id', '=', $revId)->first();
133 if ($revision === null) {
134 throw new NotFoundException("Revision #{$revId} not found");
137 // Check if it's the latest revision, cannot delete the latest revision.
138 if (intval($page->currentRevision->id ?? null) === intval($revId)) {
139 $this->showErrorNotification(trans('entities.revision_cannot_delete_latest'));
141 return redirect($page->getUrl('/revisions'));
145 Activity::add(ActivityType::REVISION_DELETE, $revision);
146 $this->showSuccessNotification(trans('entities.revision_delete_success'));
148 return redirect($page->getUrl('/revisions'));