*/
public function show(Request $request, ActivityQueries $activities, string $slug)
{
- $book = $this->queries->findVisibleBySlug($slug);
+ $book = $this->queries->findVisibleBySlugOrFail($slug);
$bookChildren = (new BookContents($book))->getTree(true);
$bookParentShelves = $book->shelves()->scopes('visible')->get();
*/
public function edit(string $slug)
{
- $book = $this->queries->findVisibleBySlug($slug);
+ $book = $this->queries->findVisibleBySlugOrFail($slug);
$this->checkOwnablePermission('book-update', $book);
$this->setPageTitle(trans('entities.books_edit_named', ['bookName' => $book->getShortName()]));
*/
public function update(Request $request, string $slug)
{
- $book = $this->queries->findVisibleBySlug($slug);
+ $book = $this->queries->findVisibleBySlugOrFail($slug);
$this->checkOwnablePermission('book-update', $book);
$validated = $this->validate($request, [
*/
public function showDelete(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('book-delete', $book);
$this->setPageTitle(trans('entities.books_delete_named', ['bookName' => $book->getShortName()]));
*/
public function destroy(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('book-delete', $book);
$this->bookRepo->destroy($book);
*/
public function showCopy(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('book-view', $book);
session()->flashInput(['name' => $book->name]);
*/
public function copy(Request $request, Cloner $cloner, string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('book-view', $book);
$this->checkPermission('book-create-all');
*/
public function convertToShelf(HierarchyTransformer $transformer, string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('book-update', $book);
$this->checkOwnablePermission('book-delete', $book);
$this->checkPermission('bookshelf-create-all');
*/
public function pdf(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$pdfContent = $this->exportFormatter->bookToPdf($book);
return $this->download()->directly($pdfContent, $bookSlug . '.pdf');
*/
public function html(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$htmlContent = $this->exportFormatter->bookToContainedHtml($book);
return $this->download()->directly($htmlContent, $bookSlug . '.html');
*/
public function plainText(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$textContent = $this->exportFormatter->bookToPlainText($book);
return $this->download()->directly($textContent, $bookSlug . '.txt');
*/
public function markdown(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$textContent = $this->exportFormatter->bookToMarkdown($book);
return $this->download()->directly($textContent, $bookSlug . '.md');
*/
public function show(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('book-update', $book);
$bookChildren = (new BookContents($book))->getTree(false);
*/
public function showItem(string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$bookChildren = (new BookContents($book))->getTree();
return view('books.parts.sort-box', ['book' => $book, 'bookChildren' => $bookChildren]);
*/
public function update(Request $request, string $bookSlug)
{
- $book = $this->queries->findVisibleBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('book-update', $book);
// Return if no map sent
*/
public function show(Request $request, ActivityQueries $activities, string $slug)
{
- $shelf = $this->queries->findVisibleBySlug($slug);
+ $shelf = $this->queries->findVisibleBySlugOrFail($slug);
$this->checkOwnablePermission('bookshelf-view', $shelf);
$listOptions = SimpleListOptions::fromRequest($request, 'shelf_books')->withSortOptions([
*/
public function edit(string $slug)
{
- $shelf = $this->queries->findVisibleBySlug($slug);
+ $shelf = $this->queries->findVisibleBySlugOrFail($slug);
$this->checkOwnablePermission('bookshelf-update', $shelf);
$shelfBookIds = $shelf->books()->get(['id'])->pluck('id');
*/
public function update(Request $request, string $slug)
{
- $shelf = $this->queries->findVisibleBySlug($slug);
+ $shelf = $this->queries->findVisibleBySlugOrFail($slug);
$this->checkOwnablePermission('bookshelf-update', $shelf);
$validated = $this->validate($request, [
'name' => ['required', 'string', 'max:255'],
*/
public function showDelete(string $slug)
{
- $shelf = $this->queries->findVisibleBySlug($slug);
+ $shelf = $this->queries->findVisibleBySlugOrFail($slug);
$this->checkOwnablePermission('bookshelf-delete', $shelf);
$this->setPageTitle(trans('entities.shelves_delete_named', ['name' => $shelf->getShortName()]));
*/
public function destroy(string $slug)
{
- $shelf = $this->queries->findVisibleBySlug($slug);
+ $shelf = $this->queries->findVisibleBySlugOrFail($slug);
$this->checkOwnablePermission('bookshelf-delete', $shelf);
$this->shelfRepo->destroy($shelf);
*/
public function create(string $bookSlug)
{
- $book = $this->entityQueries->books->findVisibleBySlug($bookSlug);
+ $book = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('chapter-create', $book);
$this->setPageTitle(trans('entities.chapters_create'));
'default_template_id' => ['nullable', 'integer'],
]);
- $book = $this->entityQueries->books->findVisibleBySlug($bookSlug);
+ $book = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug);
$this->checkOwnablePermission('chapter-create', $book);
$chapter = $this->chapterRepo->create($validated, $book);
*/
public function show(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-view', $chapter);
$sidebarTree = (new BookContents($chapter->book))->getTree();
*/
public function edit(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-update', $chapter);
$this->setPageTitle(trans('entities.chapters_edit_named', ['chapterName' => $chapter->getShortName()]));
'default_template_id' => ['nullable', 'integer'],
]);
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-update', $chapter);
$this->chapterRepo->update($chapter, $validated);
*/
public function showDelete(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-delete', $chapter);
$this->setPageTitle(trans('entities.chapters_delete_named', ['chapterName' => $chapter->getShortName()]));
*/
public function destroy(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-delete', $chapter);
$this->chapterRepo->destroy($chapter);
*/
public function showMove(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->setPageTitle(trans('entities.chapters_move_named', ['chapterName' => $chapter->getShortName()]));
$this->checkOwnablePermission('chapter-update', $chapter);
$this->checkOwnablePermission('chapter-delete', $chapter);
*/
public function move(Request $request, string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-update', $chapter);
$this->checkOwnablePermission('chapter-delete', $chapter);
*/
public function showCopy(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-view', $chapter);
session()->flashInput(['name' => $chapter->name]);
*/
public function copy(Request $request, Cloner $cloner, string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-view', $chapter);
$entitySelection = $request->get('entity_selection') ?: null;
*/
public function convertToBook(HierarchyTransformer $transformer, string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$this->checkOwnablePermission('chapter-update', $chapter);
$this->checkOwnablePermission('chapter-delete', $chapter);
$this->checkPermission('book-create-all');
*/
public function pdf(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$pdfContent = $this->exportFormatter->chapterToPdf($chapter);
return $this->download()->directly($pdfContent, $chapterSlug . '.pdf');
*/
public function html(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$containedHtml = $this->exportFormatter->chapterToContainedHtml($chapter);
return $this->download()->directly($containedHtml, $chapterSlug . '.html');
*/
public function plainText(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$chapterText = $this->exportFormatter->chapterToPlainText($chapter);
return $this->download()->directly($chapterText, $chapterSlug . '.txt');
*/
public function markdown(string $bookSlug, string $chapterSlug)
{
- $chapter = $this->queries->findVisibleBySlugs($bookSlug, $chapterSlug);
+ $chapter = $this->queries->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
$chapterText = $this->exportFormatter->chapterToMarkdown($chapter);
return $this->download()->directly($chapterText, $chapterSlug . '.md');
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Page;
+use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Exceptions\PermissionsException;
use BookStack\Http\ApiController;
];
public function __construct(
- protected PageRepo $pageRepo
+ protected PageRepo $pageRepo,
+ protected PageQueries $queries,
) {
}
*/
public function read(string $id)
{
- $page = $this->pageRepo->getById($id, []);
+ $page = $this->queries->findVisibleByIdOrFail($id);
return response()->json($page->forJsonDisplay());
}
{
$requestData = $this->validate($request, $this->rules['update']);
- $page = $this->pageRepo->getById($id, []);
+ $page = $this->queries->findVisibleByIdOrFail($id);
$this->checkOwnablePermission('page-update', $page);
$parent = null;
*/
public function delete(string $id)
{
- $page = $this->pageRepo->getById($id, []);
+ $page = $this->queries->findVisibleByIdOrFail($id);
$this->checkOwnablePermission('page-delete', $page);
$this->pageRepo->destroy($page);
{
public function __construct(
protected PageRepo $pageRepo,
- protected PageQueries $pageQueries,
+ protected PageQueries $queries,
protected EntityQueries $entityQueries,
protected ReferenceFetcher $referenceFetcher
) {
*/
public function create(string $bookSlug, string $chapterSlug = null)
{
- $parent = $this->pageRepo->getParentFromSlugs($bookSlug, $chapterSlug);
+ if ($chapterSlug) {
+ $parent = $this->entityQueries->chapters->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
+ } else {
+ $parent = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug);
+ }
+
$this->checkOwnablePermission('page-create', $parent);
// Redirect to draft edit screen if signed in
'name' => ['required', 'string', 'max:255'],
]);
- $parent = $this->pageRepo->getParentFromSlugs($bookSlug, $chapterSlug);
+ if ($chapterSlug) {
+ $parent = $this->entityQueries->chapters->findVisibleBySlugsOrFail($bookSlug, $chapterSlug);
+ } else {
+ $parent = $this->entityQueries->books->findVisibleBySlugOrFail($bookSlug);
+ }
+
$this->checkOwnablePermission('page-create', $parent);
$page = $this->pageRepo->getNewDraftPage($parent);
*/
public function editDraft(Request $request, string $bookSlug, int $pageId)
{
- $draft = $this->pageRepo->getById($pageId);
+ $draft = $this->queries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission('page-create', $draft->getParent());
- $editorData = new PageEditorData($draft, $this->pageRepo, $request->query('editor', ''));
+ $editorData = new PageEditorData($draft, $this->entityQueries, $request->query('editor', ''));
$this->setPageTitle(trans('entities.pages_edit_draft'));
return view('pages.edit', $editorData->getViewData());
$this->validate($request, [
'name' => ['required', 'string', 'max:255'],
]);
- $draftPage = $this->pageRepo->getById($pageId);
+ $draftPage = $this->queries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission('page-create', $draftPage->getParent());
$page = $this->pageRepo->publishDraft($draftPage, $request->all());
public function show(string $bookSlug, string $pageSlug)
{
try {
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
} catch (NotFoundException $e) {
- $page = $this->pageRepo->getByOldSlug($bookSlug, $pageSlug);
+ $revision = $this->entityQueries->revisions->findLatestVersionBySlugs($bookSlug, $pageSlug);
+ $page = $revision->page ?? null;
- if ($page === null) {
+ if (is_null($page)) {
throw $e;
}
*/
public function getPageAjax(int $pageId)
{
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->queries->findVisibleByIdOrFail($pageId);
$page->setHidden(array_diff($page->getHidden(), ['html', 'markdown']));
$page->makeHidden(['book']);
*/
public function edit(Request $request, string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-update', $page);
- $editorData = new PageEditorData($page, $this->pageRepo, $request->query('editor', ''));
+ $editorData = new PageEditorData($page, $this->entityQueries, $request->query('editor', ''));
if ($editorData->getWarnings()) {
$this->showWarningNotification(implode("\n", $editorData->getWarnings()));
}
$this->validate($request, [
'name' => ['required', 'string', 'max:255'],
]);
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-update', $page);
$this->pageRepo->update($page, $request->all());
*/
public function saveDraft(Request $request, int $pageId)
{
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->queries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission('page-update', $page);
if (!$this->isSignedIn()) {
*/
public function redirectFromLink(int $pageId)
{
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->queries->findVisibleByIdOrFail($pageId);
return redirect($page->getUrl());
}
*/
public function showDelete(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-delete', $page);
$this->setPageTitle(trans('entities.pages_delete_named', ['pageName' => $page->getShortName()]));
$usedAsTemplate =
*/
public function showDeleteDraft(string $bookSlug, int $pageId)
{
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->queries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission('page-update', $page);
$this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName' => $page->getShortName()]));
$usedAsTemplate =
*/
public function destroy(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-delete', $page);
$parent = $page->getParent();
*/
public function destroyDraft(string $bookSlug, int $pageId)
{
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->queries->findVisibleByIdOrFail($pageId);
$book = $page->book;
$chapter = $page->chapter;
$this->checkOwnablePermission('page-update', $page);
*/
public function showMove(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-update', $page);
$this->checkOwnablePermission('page-delete', $page);
*/
public function move(Request $request, string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-update', $page);
$this->checkOwnablePermission('page-delete', $page);
*/
public function showCopy(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-view', $page);
session()->flashInput(['name' => $page->name]);
*/
public function copy(Request $request, Cloner $cloner, string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-view', $page);
$entitySelection = $request->get('entity_selection') ?: null;
namespace BookStack\Entities\Controllers;
-use BookStack\Entities\Repos\PageRepo;
+use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Tools\ExportFormatter;
use BookStack\Entities\Tools\PageContent;
use BookStack\Exceptions\NotFoundException;
class PageExportController extends Controller
{
- protected $pageRepo;
- protected $exportFormatter;
-
- /**
- * PageExportController constructor.
- */
- public function __construct(PageRepo $pageRepo, ExportFormatter $exportFormatter)
- {
- $this->pageRepo = $pageRepo;
- $this->exportFormatter = $exportFormatter;
+ public function __construct(
+ protected PageQueries $queries,
+ protected ExportFormatter $exportFormatter,
+ ) {
$this->middleware('can:content-export');
}
*/
public function pdf(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$page->html = (new PageContent($page))->render();
$pdfContent = $this->exportFormatter->pageToPdf($page);
*/
public function html(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$page->html = (new PageContent($page))->render();
$containedHtml = $this->exportFormatter->pageToContainedHtml($page);
*/
public function plainText(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$pageText = $this->exportFormatter->pageToPlainText($page);
return $this->download()->directly($pageText, $pageSlug . '.txt');
*/
public function markdown(string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$pageText = $this->exportFormatter->pageToMarkdown($page);
return $this->download()->directly($pageText, $pageSlug . '.md');
use BookStack\Activity\ActivityType;
use BookStack\Entities\Models\PageRevision;
+use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Entities\Repos\RevisionRepo;
use BookStack\Entities\Tools\PageContent;
{
public function __construct(
protected PageRepo $pageRepo,
+ protected PageQueries $pageQueries,
protected RevisionRepo $revisionRepo,
) {
}
*/
public function index(Request $request, string $bookSlug, string $pageSlug)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->pageQueries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$listOptions = SimpleListOptions::fromRequest($request, 'page_revisions', true)->withSortOptions([
'id' => trans('entities.pages_revisions_sort_number')
]);
*/
public function show(string $bookSlug, string $pageSlug, int $revisionId)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->pageQueries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
/** @var ?PageRevision $revision */
$revision = $page->revisions()->where('id', '=', $revisionId)->first();
if ($revision === null) {
*/
public function changes(string $bookSlug, string $pageSlug, int $revisionId)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->pageQueries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
/** @var ?PageRevision $revision */
$revision = $page->revisions()->where('id', '=', $revisionId)->first();
if ($revision === null) {
*/
public function restore(string $bookSlug, string $pageSlug, int $revisionId)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->pageQueries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-update', $page);
$page = $this->pageRepo->restoreRevision($page, $revisionId);
*/
public function destroy(string $bookSlug, string $pageSlug, int $revId)
{
- $page = $this->pageRepo->getBySlug($bookSlug, $pageSlug);
+ $page = $this->pageQueries->findVisibleBySlugsOrFail($bookSlug, $pageSlug);
$this->checkOwnablePermission('page-delete', $page);
$revision = $page->revisions()->where('id', '=', $revId)->first();
*/
public function destroyUserDraft(string $pageId)
{
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->pageQueries->findVisibleByIdOrFail($pageId);
$this->revisionRepo->deleteDraftsForCurrentUser($page);
return response('', 200);
namespace BookStack\Entities\Controllers;
+use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Exceptions\NotFoundException;
use BookStack\Http\Controller;
class PageTemplateController extends Controller
{
- protected $pageRepo;
-
- /**
- * PageTemplateController constructor.
- */
- public function __construct(PageRepo $pageRepo)
- {
- $this->pageRepo = $pageRepo;
+ public function __construct(
+ protected PageRepo $pageRepo,
+ protected PageQueries $pageQueries,
+ ) {
}
/**
{
$page = $request->get('page', 1);
$search = $request->get('search', '');
- $templates = $this->pageRepo->getTemplates(10, $page, $search);
+ $count = 10;
+
+ $query = $this->pageQueries->visibleTemplates()
+ ->orderBy('name', 'asc')
+ ->skip(($page - 1) * $count)
+ ->take($count);
+
+ if ($search) {
+ $query->where('name', 'like', '%' . $search . '%');
+ }
+
+ $templates = $query->paginate($count, ['*'], 'page', $page);
+ $templates->withPath('/templates');
if ($search) {
$templates->appends(['search' => $search]);
*/
public function get(int $templateId)
{
- $page = $this->pageRepo->getById($templateId);
+ $page = $this->pageQueries->findVisibleByIdOrFail($templateId);
if (!$page->template) {
throw new NotFoundException();
return $this->start()->scopes('visible')->find($id);
}
- public function findVisibleBySlug(string $slug): Book
+ public function findVisibleBySlugOrFail(string $slug): Book
{
/** @var ?Book $book */
$book = $this->start()
return $this->start()->scopes('visible')->find($id);
}
- public function findVisibleBySlug(string $slug): Bookshelf
+ public function findVisibleBySlugOrFail(string $slug): Bookshelf
{
/** @var ?Bookshelf $shelf */
$shelf = $this->start()
return $this->start()->scopes('visible')->find($id);
}
- public function findVisibleBySlugs(string $bookSlug, string $chapterSlug): Chapter
+ public function findVisibleBySlugsOrFail(string $bookSlug, string $chapterSlug): Chapter
{
/** @var ?Chapter $chapter */
$chapter = $this->start()->with('book')
->where('slug', '=', $chapterSlug)
->first();
- if ($chapter === null) {
+ if (is_null($chapter)) {
throw new NotFoundException(trans('errors.chapter_not_found'));
}
public BookQueries $books,
public ChapterQueries $chapters,
public PageQueries $pages,
+ public PageRevisionQueries $revisions,
) {
}
namespace BookStack\Entities\Queries;
use BookStack\Entities\Models\Page;
+use BookStack\Exceptions\NotFoundException;
use Illuminate\Database\Eloquent\Builder;
class PageQueries implements ProvidesEntityQueries
return $this->start()->scopes('visible')->find($id);
}
+ public function findVisibleByIdOrFail(int $id): Page
+ {
+ $page = $this->findVisibleById($id);
+
+ if (is_null($page)) {
+ throw new NotFoundException(trans('errors.page_not_found'));
+ }
+
+ return $page;
+ }
+
+ public function findVisibleBySlugsOrFail(string $bookSlug, string $pageSlug): Page
+ {
+ /** @var ?Page $page */
+ $page = $this->start()->with('book')
+ ->whereHas('book', function (Builder $query) use ($bookSlug) {
+ $query->where('slug', '=', $bookSlug);
+ })
+ ->where('slug', '=', $pageSlug)
+ ->first();
+
+ if (is_null($page)) {
+ throw new NotFoundException(trans('errors.chapter_not_found'));
+ }
+
+ return $page;
+ }
+
public function visibleForList(): Builder
{
return $this->start()
->where('draft', '=', true)
->where('created_by', '=', user()->id);
}
+
+ public function visibleTemplates(): Builder
+ {
+ return $this->visibleForList()
+ ->where('template', '=', true);
+ }
}
--- /dev/null
+<?php
+
+namespace BookStack\Entities\Queries;
+
+use BookStack\Entities\Models\PageRevision;
+use Illuminate\Database\Eloquent\Builder;
+
+class PageRevisionQueries
+{
+ public function start(): Builder
+ {
+ return PageRevision::query();
+ }
+
+ public function findLatestVersionBySlugs(string $bookSlug, string $pageSlug): ?PageRevision
+ {
+ return PageRevision::query()
+ ->whereHas('page', function (Builder $query) {
+ $query->scopes('visible');
+ })
+ ->where('slug', '=', $pageSlug)
+ ->where('type', '=', 'version')
+ ->where('book_slug', '=', $bookSlug)
+ ->orderBy('created_at', 'desc')
+ ->first();
+ }
+
+ public function findLatestCurrentUserDraftsForPageId(int $pageId): ?PageRevision
+ {
+ return $this->latestCurrentUserDraftsForPageId($pageId)->first();
+ }
+
+ public function latestCurrentUserDraftsForPageId(int $pageId): Builder
+ {
+ return $this->start()
+ ->where('created_by', '=', user()->id)
+ ->where('type', 'update_draft')
+ ->where('page_id', '=', $pageId)
+ ->orderBy('created_at', 'desc');
+ }
+}
namespace BookStack\Entities\Queries;
-use BookStack\Entities\Models\Entity;
+use BookStack\App\Model;
use Illuminate\Database\Eloquent\Builder;
+/**
+ * Interface for our classes which provide common queries for our
+ * entity objects. Ideally all queries for entities should run through
+ * these classes.
+ * Any added methods should return a builder instances to allow extension
+ * via building on the query, unless the method starts with 'find'
+ * in which case an entity object should be returned.
+ * (nullable unless it's a *OrFail method).
+ */
interface ProvidesEntityQueries
{
public function start(): Builder;
use BookStack\Entities\Tools\PageEditorData;
use BookStack\Entities\Tools\TrashCan;
use BookStack\Exceptions\MoveOperationException;
-use BookStack\Exceptions\NotFoundException;
use BookStack\Exceptions\PermissionsException;
use BookStack\Facades\Activity;
use BookStack\References\ReferenceStore;
use BookStack\References\ReferenceUpdater;
use Exception;
-use Illuminate\Pagination\LengthAwarePaginator;
class PageRepo
{
) {
}
- /**
- * Get a page by ID.
- *
- * @throws NotFoundException
- */
- public function getById(int $id, array $relations = ['book']): Page
- {
- /** @var Page $page */
- $page = Page::visible()->with($relations)->find($id);
-
- if (!$page) {
- throw new NotFoundException(trans('errors.page_not_found'));
- }
-
- return $page;
- }
-
- /**
- * Get a page its book and own slug.
- *
- * @throws NotFoundException
- */
- public function getBySlug(string $bookSlug, string $pageSlug): Page
- {
- $page = Page::visible()->whereSlugs($bookSlug, $pageSlug)->first();
-
- if (!$page) {
- throw new NotFoundException(trans('errors.page_not_found'));
- }
-
- return $page;
- }
-
- /**
- * Get a page by its old slug but checking the revisions table
- * for the last revision that matched the given page and book slug.
- */
- public function getByOldSlug(string $bookSlug, string $pageSlug): ?Page
- {
- $revision = $this->revisionRepo->getBySlugs($bookSlug, $pageSlug);
-
- return $revision->page ?? null;
- }
-
- /**
- * Get pages that have been marked as a template.
- */
- public function getTemplates(int $count = 10, int $page = 1, string $search = ''): LengthAwarePaginator
- {
- $query = Page::visible()
- ->where('template', '=', true)
- ->orderBy('name', 'asc')
- ->skip(($page - 1) * $count)
- ->take($count);
-
- if ($search) {
- $query->where('name', 'like', '%' . $search . '%');
- }
-
- $paginator = $query->paginate($count, ['*'], 'page', $page);
- $paginator->withPath('/templates');
-
- return $paginator;
- }
-
- /**
- * Get a parent item via slugs.
- */
- public function getParentFromSlugs(string $bookSlug, string $chapterSlug = null): Entity
- {
- if ($chapterSlug !== null) {
- return Chapter::visible()->whereSlugs($bookSlug, $chapterSlug)->firstOrFail();
- }
-
- return Book::visible()->where('slug', '=', $bookSlug)->firstOrFail();
- }
-
- /**
- * Get the draft copy of the given page for the current user.
- */
- public function getUserDraft(Page $page): ?PageRevision
- {
- return $this->revisionRepo->getLatestDraftForCurrentUser($page);
- }
-
/**
* Get a new draft page belonging to the given parent entity.
*/
use BookStack\Activity\Tools\CommentTree;
use BookStack\Entities\Models\Page;
-use BookStack\Entities\Repos\PageRepo;
+use BookStack\Entities\Queries\EntityQueries;
use BookStack\Entities\Tools\Markdown\HtmlToMarkdown;
use BookStack\Entities\Tools\Markdown\MarkdownToHtml;
public function __construct(
protected Page $page,
- protected PageRepo $pageRepo,
+ protected EntityQueries $queries,
protected string $requestedEditor
) {
$this->viewData = $this->build();
{
$page = clone $this->page;
$isDraft = boolval($this->page->draft);
- $templates = $this->pageRepo->getTemplates(10);
+ $templates = $this->queries->pages->visibleTemplates()
+ ->orderBy('name', 'asc')
+ ->take(10)
+ ->get();
+
$draftsEnabled = auth()->check();
$isDraftRevision = false;
}
// Check for a current draft version for this user
- $userDraft = $this->pageRepo->getUserDraft($page);
- if ($userDraft !== null) {
+ $userDraft = $this->queries->revisions->findLatestCurrentUserDraftsForPageId($page->id)->first();
+ if (!is_null($userDraft)) {
$page->forceFill($userDraft->only(['name', 'html', 'markdown']));
$isDraftRevision = true;
$this->warnings[] = $editActivity->getEditingActiveDraftMessage($userDraft);
namespace BookStack\Uploads\Controllers;
+use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Repos\PageRepo;
use BookStack\Exceptions\FileUploadException;
use BookStack\Exceptions\NotFoundException;
{
public function __construct(
protected AttachmentService $attachmentService,
+ protected PageQueries $pageQueries,
protected PageRepo $pageRepo
) {
}
]);
$pageId = $request->get('uploaded_to');
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->pageQueries->findVisibleByIdOrFail($pageId);
$this->checkPermission('attachment-create-all');
$this->checkOwnablePermission('page-update', $page);
]), 422);
}
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->pageQueries->findVisibleByIdOrFail($pageId);
$this->checkPermission('attachment-create-all');
$this->checkOwnablePermission('page-update', $page);
*/
public function listForPage(int $pageId)
{
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->pageQueries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission('page-view', $page);
return view('attachments.manager-list', [
$this->validate($request, [
'order' => ['required', 'array'],
]);
- $page = $this->pageRepo->getById($pageId);
+ $page = $this->pageQueries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission('page-update', $page);
$attachmentOrder = $request->get('order');
$attachment = Attachment::query()->findOrFail($attachmentId);
try {
- $page = $this->pageRepo->getById($attachment->uploaded_to);
+ $page = $this->pageQueries->findVisibleByIdOrFail($attachment->uploaded_to);
} catch (NotFoundException $exception) {
throw new NotFoundException(trans('errors.attachment_not_found'));
}