use BookStack\Activity\ActivityQueries;
use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Page;
-use BookStack\Entities\Queries\PageQueries;
+use BookStack\Entities\Queries\EntityQueries;
use BookStack\Entities\Queries\RecentlyViewed;
use BookStack\Entities\Queries\TopFavourites;
-use BookStack\Entities\Repos\BookRepo;
use BookStack\Entities\Repos\BookshelfRepo;
use BookStack\Entities\Tools\PageContent;
use BookStack\Http\Controller;
class HomeController extends Controller
{
+ public function __construct(
+ protected EntityQueries $queries,
+ ) {
+ }
+
/**
* Display the homepage.
*/
$draftPages = [];
if ($this->isSignedIn()) {
- $draftPages = PageQueries::currentUserDraftsForList()
+ $draftPages = $this->queries->pages->currentUserDraftsForList()
->orderBy('updated_at', 'desc')
->with('book')
->take(6)
(new RecentlyViewed())->run(12 * $recentFactor, 1)
: Book::visible()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get();
$favourites = (new TopFavourites())->run(6);
- $recentlyUpdatedPages = PageQueries::visibleForList()
+ $recentlyUpdatedPages = $this->queries->pages->visibleForList()
->where('draft', false)
->orderBy('updated_at', 'desc')
->take($favourites->count() > 0 ? 5 : 10)
}
if ($homepageOption === 'books') {
- $books = app()->make(BookRepo::class)->getAllPaginated(18, $commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder());
+ $books = $this->queries->books->visibleForListWithCover()
+ ->orderBy($commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder())
+ ->paginate(18);
$data = array_merge($commonData, ['books' => $books]);
return view('home.books', $data);
$homepageSetting = setting('app-homepage', '0:');
$id = intval(explode(':', $homepageSetting)[0]);
/** @var Page $customHomepage */
- $customHomepage = PageQueries::start()->where('draft', '=', false)->findOrFail($id);
+ $customHomepage = $this->queries->pages->start()->where('draft', '=', false)->findOrFail($id);
$pageContent = new PageContent($customHomepage);
$customHomepage->html = $pageContent->render(false);
use BookStack\Activity\Models\View;
use BookStack\Activity\Tools\UserEntityWatchOptions;
use BookStack\Entities\Models\Bookshelf;
+use BookStack\Entities\Queries\BookQueries;
use BookStack\Entities\Repos\BookRepo;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Tools\Cloner;
public function __construct(
protected ShelfContext $shelfContext,
protected BookRepo $bookRepo,
- protected ReferenceFetcher $referenceFetcher
+ protected BookQueries $queries,
+ protected ReferenceFetcher $referenceFetcher,
) {
}
'updated_at' => trans('common.sort_updated_at'),
]);
- $books = $this->bookRepo->getAllPaginated(18, $listOptions->getSort(), $listOptions->getOrder());
- $recents = $this->isSignedIn() ? $this->bookRepo->getRecentlyViewed(4) : false;
- $popular = $this->bookRepo->getPopular(4);
- $new = $this->bookRepo->getRecentlyCreated(4);
+ $books = $this->queries->visibleForListWithCover()
+ ->orderBy($listOptions->getSort(), $listOptions->getOrder())
+ ->paginate(18);
+ $recents = $this->isSignedIn() ? $this->queries->recentlyViewedForCurrentUser()->take(4)->get() : false;
+ $popular = $this->queries->popularForList()->take(4)->get();
+ $new = $this->queries->visibleForList()->orderBy('created_at', 'desc')->take(4)->get();
$this->shelfContext->clearShelfContext();
*/
public function show(Request $request, ActivityQueries $activities, string $slug)
{
- $book = $this->bookRepo->getBySlug($slug);
+ $book = $this->queries->findVisibleBySlug($slug);
$bookChildren = (new BookContents($book))->getTree(true);
$bookParentShelves = $book->shelves()->scopes('visible')->get();
*/
public function edit(string $slug)
{
- $book = $this->bookRepo->getBySlug($slug);
+ $book = $this->queries->findVisibleBySlug($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->bookRepo->getBySlug($slug);
+ $book = $this->queries->findVisibleBySlug($slug);
$this->checkOwnablePermission('book-update', $book);
$validated = $this->validate($request, [
*/
public function showDelete(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$this->checkOwnablePermission('book-delete', $book);
$this->setPageTitle(trans('entities.books_delete_named', ['bookName' => $book->getShortName()]));
*/
public function destroy(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$this->checkOwnablePermission('book-delete', $book);
$this->bookRepo->destroy($book);
*/
public function showCopy(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$this->checkOwnablePermission('book-view', $book);
session()->flashInput(['name' => $book->name]);
*/
public function copy(Request $request, Cloner $cloner, string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$this->checkOwnablePermission('book-view', $book);
$this->checkPermission('book-create-all');
*/
public function convertToShelf(HierarchyTransformer $transformer, string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$this->checkOwnablePermission('book-update', $book);
$this->checkOwnablePermission('book-delete', $book);
$this->checkPermission('bookshelf-create-all');
namespace BookStack\Entities\Controllers;
-use BookStack\Entities\Repos\BookRepo;
+use BookStack\Entities\Queries\BookQueries;
use BookStack\Entities\Tools\ExportFormatter;
use BookStack\Http\Controller;
use Throwable;
class BookExportController extends Controller
{
- protected $bookRepo;
- protected $exportFormatter;
-
- /**
- * BookExportController constructor.
- */
- public function __construct(BookRepo $bookRepo, ExportFormatter $exportFormatter)
- {
- $this->bookRepo = $bookRepo;
- $this->exportFormatter = $exportFormatter;
+ public function __construct(
+ protected BookQueries $queries,
+ protected ExportFormatter $exportFormatter,
+ ) {
$this->middleware('can:content-export');
}
*/
public function pdf(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$pdfContent = $this->exportFormatter->bookToPdf($book);
return $this->download()->directly($pdfContent, $bookSlug . '.pdf');
*/
public function html(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$htmlContent = $this->exportFormatter->bookToContainedHtml($book);
return $this->download()->directly($htmlContent, $bookSlug . '.html');
*/
public function plainText(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$textContent = $this->exportFormatter->bookToPlainText($book);
return $this->download()->directly($textContent, $bookSlug . '.txt');
*/
public function markdown(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$textContent = $this->exportFormatter->bookToMarkdown($book);
return $this->download()->directly($textContent, $bookSlug . '.md');
namespace BookStack\Entities\Controllers;
use BookStack\Activity\ActivityType;
-use BookStack\Entities\Repos\BookRepo;
+use BookStack\Entities\Queries\BookQueries;
use BookStack\Entities\Tools\BookContents;
use BookStack\Entities\Tools\BookSortMap;
use BookStack\Facades\Activity;
class BookSortController extends Controller
{
- protected $bookRepo;
-
- public function __construct(BookRepo $bookRepo)
- {
- $this->bookRepo = $bookRepo;
+ public function __construct(
+ protected BookQueries $queries,
+ ) {
}
/**
*/
public function show(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$this->checkOwnablePermission('book-update', $book);
$bookChildren = (new BookContents($book))->getTree(false);
*/
public function showItem(string $bookSlug)
{
- $book = $this->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($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->bookRepo->getBySlug($bookSlug);
+ $book = $this->queries->findVisibleBySlug($bookSlug);
$this->checkOwnablePermission('book-update', $book);
// Return if no map sent
--- /dev/null
+<?php
+
+namespace BookStack\Entities\Queries;
+
+use BookStack\Entities\Models\Book;
+use BookStack\Exceptions\NotFoundException;
+use Illuminate\Database\Eloquent\Builder;
+
+class BookQueries
+{
+ public function start(): Builder
+ {
+ return Book::query();
+ }
+
+ public function findVisibleBySlug(string $slug): Book
+ {
+ /** @var ?Book $book */
+ $book = $this->start()
+ ->scopes('visible')
+ ->where('slug', '=', $slug)
+ ->first();
+
+ if ($book === null) {
+ throw new NotFoundException(trans('errors.book_not_found'));
+ }
+
+ return $book;
+ }
+
+ public function visibleForList(): Builder
+ {
+ return $this->start()->scopes('visible');
+ }
+
+ public function visibleForListWithCover(): Builder
+ {
+ return $this->visibleForList()->with('cover');
+ }
+
+ public function recentlyViewedForCurrentUser(): Builder
+ {
+ return $this->visibleForList()
+ ->scopes('withLastView')
+ ->having('last_viewed_at', '>', 0)
+ ->orderBy('last_viewed_at', 'desc');
+ }
+
+ public function popularForList(): Builder
+ {
+ return $this->visibleForList()
+ ->scopes('withViewCount')
+ ->having('view_count', '>', 0)
+ ->orderBy('view_count', 'desc');
+ }
+}
--- /dev/null
+<?php
+
+namespace BookStack\Entities\Queries;
+
+class EntityQueries
+{
+ public function __construct(
+ public BookQueries $books,
+ public PageQueries $pages,
+ ) {
+ }
+}
class PageQueries
{
- public static function start(): Builder
+ public function start(): Builder
{
return Page::query();
}
- public static function visibleForList(): Builder
+ public function visibleForList(): Builder
{
- return Page::visible()
+ return $this->start()
->select(array_merge(Page::$listAttributes, ['book_slug' => function ($builder) {
$builder->select('slug')
->from('books')
}]));
}
- public static function currentUserDraftsForList(): Builder
+ public function currentUserDraftsForList(): Builder
{
- return static::visibleForList()
+ return $this->visibleForList()
->where('draft', '=', true)
->where('created_by', '=', user()->id);
}
use BookStack\Activity\ActivityType;
use BookStack\Activity\TagRepo;
use BookStack\Entities\Models\Book;
-use BookStack\Entities\Models\Page;
use BookStack\Entities\Tools\TrashCan;
use BookStack\Exceptions\ImageUploadException;
-use BookStack\Exceptions\NotFoundException;
use BookStack\Facades\Activity;
use BookStack\Uploads\ImageRepo;
use Exception;
-use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\UploadedFile;
-use Illuminate\Support\Collection;
class BookRepo
{
) {
}
- /**
- * Get all books in a paginated format.
- */
- public function getAllPaginated(int $count = 20, string $sort = 'name', string $order = 'asc'): LengthAwarePaginator
- {
- return Book::visible()->with('cover')->orderBy($sort, $order)->paginate($count);
- }
-
- /**
- * Get the books that were most recently viewed by this user.
- */
- public function getRecentlyViewed(int $count = 20): Collection
- {
- return Book::visible()->withLastView()
- ->having('last_viewed_at', '>', 0)
- ->orderBy('last_viewed_at', 'desc')
- ->take($count)->get();
- }
-
- /**
- * Get the most popular books in the system.
- */
- public function getPopular(int $count = 20): Collection
- {
- return Book::visible()->withViewCount()
- ->having('view_count', '>', 0)
- ->orderBy('view_count', 'desc')
- ->take($count)->get();
- }
-
- /**
- * Get the most recently created books from the system.
- */
- public function getRecentlyCreated(int $count = 20): Collection
- {
- return Book::visible()->orderBy('created_at', 'desc')
- ->take($count)->get();
- }
-
- /**
- * Get a book by its slug.
- */
- public function getBySlug(string $slug): Book
- {
- $book = Book::visible()->where('slug', '=', $slug)->first();
-
- if ($book === null) {
- throw new NotFoundException(trans('errors.book_not_found'));
- }
-
- return $book;
- }
-
/**
* Create a new book in the system.
*/