Queries: Extracted static page,chapter,shelf queries to classes

This commit is contained in:
Dan Brown 2024-02-07 21:58:27 +00:00
parent 483410749b
commit 546cfb0dcc
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
15 changed files with 93 additions and 60 deletions

View File

@ -4,6 +4,7 @@ namespace BookStack\Activity\Controllers;
use BookStack\Activity\CommentRepo;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Http\Controller;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
@ -11,7 +12,8 @@ use Illuminate\Validation\ValidationException;
class CommentController extends Controller
{
public function __construct(
protected CommentRepo $commentRepo
protected CommentRepo $commentRepo,
protected PageQueries $pageQueries,
) {
}
@ -27,7 +29,7 @@ class CommentController extends Controller
'parent_id' => ['nullable', 'integer'],
]);
$page = Page::visible()->find($pageId);
$page = $this->pageQueries->findVisibleById($pageId);
if ($page === null) {
return response('Not found', 404);
}

View File

@ -3,6 +3,7 @@
namespace BookStack\Console\Commands;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Queries\BookshelfQueries;
use BookStack\Entities\Tools\PermissionsUpdater;
use Illuminate\Console\Command;
@ -28,7 +29,7 @@ class CopyShelfPermissionsCommand extends Command
/**
* Execute the console command.
*/
public function handle(PermissionsUpdater $permissionsUpdater): int
public function handle(PermissionsUpdater $permissionsUpdater, BookshelfQueries $queries): int
{
$shelfSlug = $this->option('slug');
$cascadeAll = $this->option('all');
@ -51,11 +52,11 @@ class CopyShelfPermissionsCommand extends Command
return 0;
}
$shelves = Bookshelf::query()->get(['id']);
$shelves = $queries->start()->get(['id']);
}
if ($shelfSlug) {
$shelves = Bookshelf::query()->where('slug', '=', $shelfSlug)->get(['id']);
$shelves = $queries->start()->where('slug', '=', $shelfSlug)->get(['id']);
if ($shelves->count() === 0) {
$this->info('No shelves found with the given slug.');
}

View File

@ -8,6 +8,7 @@ use BookStack\Activity\Models\View;
use BookStack\Activity\Tools\UserEntityWatchOptions;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Queries\BookQueries;
use BookStack\Entities\Queries\BookshelfQueries;
use BookStack\Entities\Repos\BookRepo;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Tools\Cloner;
@ -29,6 +30,7 @@ class BookController extends Controller
protected ShelfContext $shelfContext,
protected BookRepo $bookRepo,
protected BookQueries $queries,
protected BookshelfQueries $shelfQueries,
protected ReferenceFetcher $referenceFetcher,
) {
}
@ -75,7 +77,7 @@ class BookController extends Controller
$bookshelf = null;
if ($shelfSlug !== null) {
$bookshelf = Bookshelf::visible()->where('slug', '=', $shelfSlug)->firstOrFail();
$bookshelf = $this->shelfQueries->findVisibleBySlugOrFail($shelfSlug);
$this->checkOwnablePermission('bookshelf-update', $bookshelf);
}
@ -105,7 +107,7 @@ class BookController extends Controller
$bookshelf = null;
if ($shelfSlug !== null) {
$bookshelf = Bookshelf::visible()->where('slug', '=', $shelfSlug)->firstOrFail();
$bookshelf = $this->shelfQueries->findVisibleBySlugOrFail($shelfSlug);
$this->checkOwnablePermission('bookshelf-update', $bookshelf);
}

View File

@ -3,6 +3,7 @@
namespace BookStack\Entities\Controllers;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Queries\BookshelfQueries;
use BookStack\Entities\Repos\BookshelfRepo;
use BookStack\Http\ApiController;
use Exception;
@ -13,7 +14,8 @@ use Illuminate\Validation\ValidationException;
class BookshelfApiController extends ApiController
{
public function __construct(
protected BookshelfRepo $bookshelfRepo
protected BookshelfRepo $bookshelfRepo,
protected BookshelfQueries $queries,
) {
}
@ -22,7 +24,7 @@ class BookshelfApiController extends ApiController
*/
public function list()
{
$shelves = Bookshelf::visible();
$shelves = $this->queries->visibleForList();
return $this->apiListingResponse($shelves, [
'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'owned_by',
@ -54,7 +56,7 @@ class BookshelfApiController extends ApiController
*/
public function read(string $id)
{
$shelf = Bookshelf::visible()->findOrFail($id);
$shelf = $this->queries->findVisibleByIdOrFail(intval($id));
$shelf = $this->forJsonDisplay($shelf);
$shelf->load([
'createdBy', 'updatedBy', 'ownedBy',
@ -78,7 +80,7 @@ class BookshelfApiController extends ApiController
*/
public function update(Request $request, string $id)
{
$shelf = Bookshelf::visible()->findOrFail($id);
$shelf = $this->queries->findVisibleByIdOrFail(intval($id));
$this->checkOwnablePermission('bookshelf-update', $shelf);
$requestData = $this->validate($request, $this->rules()['update']);
@ -97,7 +99,7 @@ class BookshelfApiController extends ApiController
*/
public function delete(string $id)
{
$shelf = Bookshelf::visible()->findOrFail($id);
$shelf = $this->queries->findVisibleByIdOrFail(intval($id));
$this->checkOwnablePermission('bookshelf-delete', $shelf);
$this->bookshelfRepo->destroy($shelf);

View File

@ -3,20 +3,17 @@
namespace BookStack\Entities\Controllers;
use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Queries\ChapterQueries;
use BookStack\Entities\Tools\ExportFormatter;
use BookStack\Http\ApiController;
use Throwable;
class ChapterExportApiController extends ApiController
{
protected $exportFormatter;
/**
* ChapterExportController constructor.
*/
public function __construct(ExportFormatter $exportFormatter)
{
$this->exportFormatter = $exportFormatter;
public function __construct(
protected ExportFormatter $exportFormatter,
protected ChapterQueries $queries,
) {
$this->middleware('can:content-export');
}
@ -27,7 +24,7 @@ class ChapterExportApiController extends ApiController
*/
public function exportPdf(int $id)
{
$chapter = Chapter::visible()->findOrFail($id);
$chapter = $this->queries->findVisibleByIdOrFail($id);
$pdfContent = $this->exportFormatter->chapterToPdf($chapter);
return $this->download()->directly($pdfContent, $chapter->slug . '.pdf');
@ -40,7 +37,7 @@ class ChapterExportApiController extends ApiController
*/
public function exportHtml(int $id)
{
$chapter = Chapter::visible()->findOrFail($id);
$chapter = $this->queries->findVisibleByIdOrFail($id);
$htmlContent = $this->exportFormatter->chapterToContainedHtml($chapter);
return $this->download()->directly($htmlContent, $chapter->slug . '.html');
@ -51,7 +48,7 @@ class ChapterExportApiController extends ApiController
*/
public function exportPlainText(int $id)
{
$chapter = Chapter::visible()->findOrFail($id);
$chapter = $this->queries->findVisibleByIdOrFail($id);
$textContent = $this->exportFormatter->chapterToPlainText($chapter);
return $this->download()->directly($textContent, $chapter->slug . '.txt');
@ -62,7 +59,7 @@ class ChapterExportApiController extends ApiController
*/
public function exportMarkdown(int $id)
{
$chapter = Chapter::visible()->findOrFail($id);
$chapter = $this->queries->findVisibleByIdOrFail($id);
$markdown = $this->exportFormatter->chapterToMarkdown($chapter);
return $this->download()->directly($markdown, $chapter->slug . '.md');

View File

@ -359,7 +359,9 @@ class PageController extends Controller
$query->scopes('visible');
};
$pages = Page::visible()->with(['updatedBy', 'book' => $visibleBelongsScope, 'chapter' => $visibleBelongsScope])
$pages = $this->queries->visibleForList()
->addSelect('updated_by')
->with(['updatedBy', 'book' => $visibleBelongsScope, 'chapter' => $visibleBelongsScope])
->orderBy('updated_at', 'desc')
->paginate(20)
->setPath(url('/pages/recently-updated'));

View File

@ -3,17 +3,17 @@
namespace BookStack\Entities\Controllers;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Tools\ExportFormatter;
use BookStack\Http\ApiController;
use Throwable;
class PageExportApiController extends ApiController
{
protected $exportFormatter;
public function __construct(ExportFormatter $exportFormatter)
{
$this->exportFormatter = $exportFormatter;
public function __construct(
protected ExportFormatter $exportFormatter,
protected PageQueries $queries,
) {
$this->middleware('can:content-export');
}
@ -24,7 +24,7 @@ class PageExportApiController extends ApiController
*/
public function exportPdf(int $id)
{
$page = Page::visible()->findOrFail($id);
$page = $this->queries->findVisibleByIdOrFail($id);
$pdfContent = $this->exportFormatter->pageToPdf($page);
return $this->download()->directly($pdfContent, $page->slug . '.pdf');
@ -37,7 +37,7 @@ class PageExportApiController extends ApiController
*/
public function exportHtml(int $id)
{
$page = Page::visible()->findOrFail($id);
$page = $this->queries->findVisibleByIdOrFail($id);
$htmlContent = $this->exportFormatter->pageToContainedHtml($page);
return $this->download()->directly($htmlContent, $page->slug . '.html');
@ -48,7 +48,7 @@ class PageExportApiController extends ApiController
*/
public function exportPlainText(int $id)
{
$page = Page::visible()->findOrFail($id);
$page = $this->queries->findVisibleByIdOrFail($id);
$textContent = $this->exportFormatter->pageToPlainText($page);
return $this->download()->directly($textContent, $page->slug . '.txt');
@ -59,7 +59,7 @@ class PageExportApiController extends ApiController
*/
public function exportMarkdown(int $id)
{
$page = Page::visible()->findOrFail($id);
$page = $this->queries->findVisibleByIdOrFail($id);
$markdown = $this->exportFormatter->pageToMarkdown($page);
return $this->download()->directly($markdown, $page->slug . '.md');

View File

@ -18,6 +18,17 @@ class BookshelfQueries implements ProvidesEntityQueries
return $this->start()->scopes('visible')->find($id);
}
public function findVisibleByIdOrFail(int $id): Bookshelf
{
$shelf = $this->findVisibleById($id);
if (is_null($shelf)) {
throw new NotFoundException(trans('errors.bookshelf_not_found'));
}
return $shelf;
}
public function findVisibleBySlugOrFail(string $slug): Bookshelf
{
/** @var ?Bookshelf $shelf */

View File

@ -9,6 +9,7 @@ use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\HasCoverImage;
use BookStack\Entities\Models\HasHtmlDescription;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Exceptions\ImageUploadException;
use BookStack\References\ReferenceStore;
use BookStack\References\ReferenceUpdater;
@ -23,6 +24,7 @@ class BaseRepo
protected ImageRepo $imageRepo,
protected ReferenceUpdater $referenceUpdater,
protected ReferenceStore $referenceStore,
protected PageQueries $pageQueries,
) {
}
@ -125,8 +127,7 @@ class BaseRepo
return;
}
$templateExists = Page::query()->visible()
->where('template', '=', true)
$templateExists = $this->pageQueries->visibleTemplates()
->where('id', '=', $templateId)
->exists();

View File

@ -3,6 +3,7 @@
namespace BookStack\Entities\Tools;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Tools\Markdown\MarkdownToHtml;
use BookStack\Exceptions\ImageUploadException;
use BookStack\Facades\Theme;
@ -21,9 +22,12 @@ use Illuminate\Support\Str;
class PageContent
{
protected PageQueries $pageQueries;
public function __construct(
protected Page $page
) {
$this->pageQueries = app()->make(PageQueries::class);
}
/**
@ -331,7 +335,7 @@ class PageContent
return PageIncludeContent::fromHtmlAndTag('', $tag);
}
$matchedPage = Page::visible()->find($tag->getPageId());
$matchedPage = $this->pageQueries->findVisibleById($tag->getPageId());
$content = PageIncludeContent::fromHtmlAndTag($matchedPage->html ?? '', $tag);
if (Theme::hasListeners(ThemeEvents::PAGE_INCLUDE_PARSE)) {

View File

@ -4,10 +4,16 @@ namespace BookStack\Entities\Tools;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf;
use BookStack\Entities\Queries\BookshelfQueries;
class ShelfContext
{
protected $KEY_SHELF_CONTEXT_ID = 'context_bookshelf_id';
protected string $KEY_SHELF_CONTEXT_ID = 'context_bookshelf_id';
public function __construct(
protected BookshelfQueries $shelfQueries,
) {
}
/**
* Get the current bookshelf context for the given book.
@ -20,8 +26,7 @@ class ShelfContext
return null;
}
/** @var Bookshelf $shelf */
$shelf = Bookshelf::visible()->find($contextBookshelfId);
$shelf = $this->shelfQueries->findVisibleById($contextBookshelfId);
$shelfContainsBook = $shelf && $shelf->contains($book);
return $shelfContainsBook ? $shelf : null;
@ -30,7 +35,7 @@ class ShelfContext
/**
* Store the current contextual shelf ID.
*/
public function setShelfContext(int $shelfId)
public function setShelfContext(int $shelfId): void
{
session()->put($this->KEY_SHELF_CONTEXT_ID, $shelfId);
}
@ -38,7 +43,7 @@ class ShelfContext
/**
* Clear the session stored shelf context id.
*/
public function clearShelfContext()
public function clearShelfContext(): void
{
session()->forget($this->KEY_SHELF_CONTEXT_ID);
}

View File

@ -3,6 +3,7 @@
namespace BookStack\Search;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Entities\Queries\Popular;
use BookStack\Entities\Tools\SiblingFetcher;
use BookStack\Http\Controller;
@ -11,7 +12,8 @@ use Illuminate\Http\Request;
class SearchController extends Controller
{
public function __construct(
protected SearchRunner $searchRunner
protected SearchRunner $searchRunner,
protected PageQueries $pageQueries,
) {
}
@ -95,12 +97,11 @@ class SearchController extends Controller
$searchOptions->setFilter('is_template');
$entities = $this->searchRunner->searchEntities($searchOptions, 'page', 1, 20)['results'];
} else {
$entities = Page::visible()
->where('template', '=', true)
$entities = $this->pageQueries->visibleTemplates()
->where('draft', '=', false)
->orderBy('updated_at', 'desc')
->take(20)
->get(Page::$listAttributes);
->get();
}
return view('search.parts.entity-selector-list', [

View File

@ -3,6 +3,7 @@
namespace BookStack\Uploads\Controllers;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Exceptions\FileUploadException;
use BookStack\Http\ApiController;
use BookStack\Uploads\Attachment;
@ -15,7 +16,8 @@ use Illuminate\Validation\ValidationException;
class AttachmentApiController extends ApiController
{
public function __construct(
protected AttachmentService $attachmentService
protected AttachmentService $attachmentService,
protected PageQueries $pageQueries,
) {
}
@ -48,7 +50,7 @@ class AttachmentApiController extends ApiController
$requestData = $this->validate($request, $this->rules()['create']);
$pageId = $request->get('uploaded_to');
$page = Page::visible()->findOrFail($pageId);
$page = $this->pageQueries->findVisibleByIdOrFail($pageId);
$this->checkOwnablePermission('page-update', $page);
if ($request->hasFile('file')) {
@ -132,7 +134,7 @@ class AttachmentApiController extends ApiController
$page = $attachment->page;
if ($requestData['uploaded_to'] ?? false) {
$pageId = $request->get('uploaded_to');
$page = Page::visible()->findOrFail($pageId);
$page = $this->pageQueries->findVisibleByIdOrFail($pageId);
$attachment->uploaded_to = $requestData['uploaded_to'];
}

View File

@ -3,6 +3,7 @@
namespace BookStack\Uploads\Controllers;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Http\ApiController;
use BookStack\Uploads\Image;
use BookStack\Uploads\ImageRepo;
@ -18,6 +19,7 @@ class ImageGalleryApiController extends ApiController
public function __construct(
protected ImageRepo $imageRepo,
protected ImageResizer $imageResizer,
protected PageQueries $pageQueries,
) {
}
@ -66,9 +68,9 @@ class ImageGalleryApiController extends ApiController
{
$this->checkPermission('image-create-all');
$data = $this->validate($request, $this->rules()['create']);
Page::visible()->findOrFail($data['uploaded_to']);
$page = $this->pageQueries->findVisibleByIdOrFail($data['uploaded_to']);
$image = $this->imageRepo->saveNew($data['image'], $data['type'], $data['uploaded_to']);
$image = $this->imageRepo->saveNew($data['image'], $data['type'], $page->id);
if (isset($data['name'])) {
$image->refresh();

View File

@ -3,6 +3,7 @@
namespace BookStack\Uploads;
use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\PageQueries;
use BookStack\Exceptions\ImageUploadException;
use BookStack\Permissions\PermissionApplicator;
use Exception;
@ -15,6 +16,7 @@ class ImageRepo
protected ImageService $imageService,
protected PermissionApplicator $permissions,
protected ImageResizer $imageResizer,
protected PageQueries $pageQueries,
) {
}
@ -77,14 +79,13 @@ class ImageRepo
*/
public function getEntityFiltered(
string $type,
string $filterType = null,
int $page = 0,
int $pageSize = 24,
int $uploadedTo = null,
string $search = null
?string $filterType,
int $page,
int $pageSize,
int $uploadedTo,
?string $search
): array {
/** @var Page $contextPage */
$contextPage = Page::visible()->findOrFail($uploadedTo);
$contextPage = $this->pageQueries->findVisibleByIdOrFail($uploadedTo);
$parentFilter = null;
if ($filterType === 'book' || $filterType === 'page') {
@ -225,9 +226,9 @@ class ImageRepo
*/
public function getPagesUsingImage(Image $image): array
{
$pages = Page::visible()
$pages = $this->pageQueries->visibleForList()
->where('html', 'like', '%' . $image->url . '%')
->get(['id', 'name', 'slug', 'book_id']);
->get();
foreach ($pages as $page) {
$page->setAttribute('url', $page->getUrl());