Skip to content

Commit ff8daad

Browse files
authored
Merge pull request #4827 from BookStackApp/query_revamp
Update of entity loading to be more efficient and avoid global addSelects
2 parents 05ac0fc + 1ea2ac8 commit ff8daad

File tree

87 files changed

+1201
-918
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+1201
-918
lines changed

app/Activity/ActivityQueries.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77
use BookStack\Entities\Models\Chapter;
88
use BookStack\Entities\Models\Entity;
99
use BookStack\Entities\Models\Page;
10+
use BookStack\Entities\Tools\MixedEntityListLoader;
1011
use BookStack\Permissions\PermissionApplicator;
1112
use BookStack\Users\Models\User;
1213
use Illuminate\Database\Eloquent\Builder;
1314
use Illuminate\Database\Eloquent\Relations\Relation;
1415

1516
class ActivityQueries
1617
{
17-
protected PermissionApplicator $permissions;
18-
19-
public function __construct(PermissionApplicator $permissions)
20-
{
21-
$this->permissions = $permissions;
18+
public function __construct(
19+
protected PermissionApplicator $permissions,
20+
protected MixedEntityListLoader $listLoader,
21+
) {
2222
}
2323

2424
/**
@@ -29,11 +29,13 @@ public function latest(int $count = 20, int $page = 0): array
2929
$activityList = $this->permissions
3030
->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type')
3131
->orderBy('created_at', 'desc')
32-
->with(['user', 'entity'])
32+
->with(['user'])
3333
->skip($count * $page)
3434
->take($count)
3535
->get();
3636

37+
$this->listLoader->loadIntoRelations($activityList->all(), 'entity', false);
38+
3739
return $this->filterSimilar($activityList);
3840
}
3941

app/Activity/Controllers/CommentController.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
namespace BookStack\Activity\Controllers;
44

55
use BookStack\Activity\CommentRepo;
6-
use BookStack\Entities\Models\Page;
6+
use BookStack\Entities\Queries\PageQueries;
77
use BookStack\Http\Controller;
88
use Illuminate\Http\Request;
99
use Illuminate\Validation\ValidationException;
1010

1111
class CommentController extends Controller
1212
{
1313
public function __construct(
14-
protected CommentRepo $commentRepo
14+
protected CommentRepo $commentRepo,
15+
protected PageQueries $pageQueries,
1516
) {
1617
}
1718

@@ -27,7 +28,7 @@ public function savePageComment(Request $request, int $pageId)
2728
'parent_id' => ['nullable', 'integer'],
2829
]);
2930

30-
$page = Page::visible()->find($pageId);
31+
$page = $this->pageQueries->findVisibleById($pageId);
3132
if ($page === null) {
3233
return response('Not found', 404);
3334
}

app/Activity/Controllers/FavouriteController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace BookStack\Activity\Controllers;
44

5-
use BookStack\Entities\Queries\TopFavourites;
5+
use BookStack\Entities\Queries\QueryTopFavourites;
66
use BookStack\Entities\Tools\MixedEntityRequestHelper;
77
use BookStack\Http\Controller;
88
use Illuminate\Http\Request;
@@ -17,11 +17,11 @@ public function __construct(
1717
/**
1818
* Show a listing of all favourite items for the current user.
1919
*/
20-
public function index(Request $request)
20+
public function index(Request $request, QueryTopFavourites $topFavourites)
2121
{
2222
$viewCount = 20;
2323
$page = intval($request->get('page', 1));
24-
$favourites = (new TopFavourites())->run($viewCount + 1, (($page - 1) * $viewCount));
24+
$favourites = $topFavourites->run($viewCount + 1, (($page - 1) * $viewCount));
2525

2626
$hasMoreLink = ($favourites->count() > $viewCount) ? url('/favourites?page=' . ($page + 1)) : null;
2727

app/Api/ApiDocsGenerator.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use Illuminate\Contracts\Container\BindingResolutionException;
88
use Illuminate\Support\Collection;
99
use Illuminate\Support\Facades\Cache;
10-
use Illuminate\Support\Facades\DB;
1110
use Illuminate\Support\Facades\Route;
1211
use Illuminate\Support\Str;
1312
use Illuminate\Validation\Rules\Password;

app/App/HomeController.php

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33
namespace BookStack\App;
44

55
use BookStack\Activity\ActivityQueries;
6-
use BookStack\Entities\Models\Book;
76
use BookStack\Entities\Models\Page;
8-
use BookStack\Entities\Queries\RecentlyViewed;
9-
use BookStack\Entities\Queries\TopFavourites;
10-
use BookStack\Entities\Repos\BookRepo;
11-
use BookStack\Entities\Repos\BookshelfRepo;
7+
use BookStack\Entities\Queries\EntityQueries;
8+
use BookStack\Entities\Queries\QueryRecentlyViewed;
9+
use BookStack\Entities\Queries\QueryTopFavourites;
1210
use BookStack\Entities\Tools\PageContent;
1311
use BookStack\Http\Controller;
1412
use BookStack\Uploads\FaviconHandler;
@@ -17,18 +15,25 @@
1715

1816
class HomeController extends Controller
1917
{
18+
public function __construct(
19+
protected EntityQueries $queries,
20+
) {
21+
}
22+
2023
/**
2124
* Display the homepage.
2225
*/
23-
public function index(Request $request, ActivityQueries $activities)
24-
{
26+
public function index(
27+
Request $request,
28+
ActivityQueries $activities,
29+
QueryRecentlyViewed $recentlyViewed,
30+
QueryTopFavourites $topFavourites,
31+
) {
2532
$activity = $activities->latest(10);
2633
$draftPages = [];
2734

2835
if ($this->isSignedIn()) {
29-
$draftPages = Page::visible()
30-
->where('draft', '=', true)
31-
->where('created_by', '=', user()->id)
36+
$draftPages = $this->queries->pages->currentUserDraftsForList()
3237
->orderBy('updated_at', 'desc')
3338
->with('book')
3439
->take(6)
@@ -37,14 +42,13 @@ public function index(Request $request, ActivityQueries $activities)
3742

3843
$recentFactor = count($draftPages) > 0 ? 0.5 : 1;
3944
$recents = $this->isSignedIn() ?
40-
(new RecentlyViewed())->run(12 * $recentFactor, 1)
41-
: Book::visible()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get();
42-
$favourites = (new TopFavourites())->run(6);
43-
$recentlyUpdatedPages = Page::visible()->with('book')
45+
$recentlyViewed->run(12 * $recentFactor, 1)
46+
: $this->queries->books->visibleForList()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get();
47+
$favourites = $topFavourites->run(6);
48+
$recentlyUpdatedPages = $this->queries->pages->visibleForList()
4449
->where('draft', false)
4550
->orderBy('updated_at', 'desc')
4651
->take($favourites->count() > 0 ? 5 : 10)
47-
->select(Page::$listAttributes)
4852
->get();
4953

5054
$homepageOptions = ['default', 'books', 'bookshelves', 'page'];
@@ -78,14 +82,18 @@ public function index(Request $request, ActivityQueries $activities)
7882
}
7983

8084
if ($homepageOption === 'bookshelves') {
81-
$shelves = app()->make(BookshelfRepo::class)->getAllPaginated(18, $commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder());
85+
$shelves = $this->queries->shelves->visibleForListWithCover()
86+
->orderBy($commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder())
87+
->paginate(18);
8288
$data = array_merge($commonData, ['shelves' => $shelves]);
8389

8490
return view('home.shelves', $data);
8591
}
8692

8793
if ($homepageOption === 'books') {
88-
$books = app()->make(BookRepo::class)->getAllPaginated(18, $commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder());
94+
$books = $this->queries->books->visibleForListWithCover()
95+
->orderBy($commonData['listOptions']->getSort(), $commonData['listOptions']->getOrder())
96+
->paginate(18);
8997
$data = array_merge($commonData, ['books' => $books]);
9098

9199
return view('home.books', $data);
@@ -95,7 +103,7 @@ public function index(Request $request, ActivityQueries $activities)
95103
$homepageSetting = setting('app-homepage', '0:');
96104
$id = intval(explode(':', $homepageSetting)[0]);
97105
/** @var Page $customHomepage */
98-
$customHomepage = Page::query()->where('draft', '=', false)->findOrFail($id);
106+
$customHomepage = $this->queries->pages->start()->where('draft', '=', false)->findOrFail($id);
99107
$pageContent = new PageContent($customHomepage);
100108
$customHomepage->html = $pageContent->render(false);
101109

app/App/Providers/ThemeServiceProvider.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use BookStack\Theming\ThemeEvents;
66
use BookStack\Theming\ThemeService;
7-
use Illuminate\Support\Facades\Route;
87
use Illuminate\Support\ServiceProvider;
98

109
class ThemeServiceProvider extends ServiceProvider

app/Config/clockwork.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@
173173

174174
// List of URIs that should not be collected
175175
'except' => [
176+
'/uploads/images/.*', // BookStack image requests
177+
176178
'/horizon/.*', // Laravel Horizon requests
177179
'/telescope/.*', // Laravel Telescope requests
178180
'/_debugbar/.*', // Laravel DebugBar requests

app/Console/Commands/CopyShelfPermissionsCommand.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace BookStack\Console\Commands;
44

5-
use BookStack\Entities\Models\Bookshelf;
5+
use BookStack\Entities\Queries\BookshelfQueries;
66
use BookStack\Entities\Tools\PermissionsUpdater;
77
use Illuminate\Console\Command;
88

@@ -28,7 +28,7 @@ class CopyShelfPermissionsCommand extends Command
2828
/**
2929
* Execute the console command.
3030
*/
31-
public function handle(PermissionsUpdater $permissionsUpdater): int
31+
public function handle(PermissionsUpdater $permissionsUpdater, BookshelfQueries $queries): int
3232
{
3333
$shelfSlug = $this->option('slug');
3434
$cascadeAll = $this->option('all');
@@ -51,11 +51,11 @@ public function handle(PermissionsUpdater $permissionsUpdater): int
5151
return 0;
5252
}
5353

54-
$shelves = Bookshelf::query()->get(['id']);
54+
$shelves = $queries->start()->get(['id']);
5555
}
5656

5757
if ($shelfSlug) {
58-
$shelves = Bookshelf::query()->where('slug', '=', $shelfSlug)->get(['id']);
58+
$shelves = $queries->start()->where('slug', '=', $shelfSlug)->get(['id']);
5959
if ($shelves->count() === 0) {
6060
$this->info('No shelves found with the given slug.');
6161
}

app/Entities/Controllers/BookApiController.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use BookStack\Entities\Models\Book;
77
use BookStack\Entities\Models\Chapter;
88
use BookStack\Entities\Models\Entity;
9+
use BookStack\Entities\Queries\BookQueries;
910
use BookStack\Entities\Repos\BookRepo;
1011
use BookStack\Entities\Tools\BookContents;
1112
use BookStack\Http\ApiController;
@@ -15,7 +16,8 @@
1516
class BookApiController extends ApiController
1617
{
1718
public function __construct(
18-
protected BookRepo $bookRepo
19+
protected BookRepo $bookRepo,
20+
protected BookQueries $queries,
1921
) {
2022
}
2123

@@ -24,7 +26,9 @@ public function __construct(
2426
*/
2527
public function list()
2628
{
27-
$books = Book::visible();
29+
$books = $this->queries
30+
->visibleForList()
31+
->addSelect(['created_by', 'updated_by']);
2832

2933
return $this->apiListingResponse($books, [
3034
'id', 'name', 'slug', 'description', 'created_at', 'updated_at', 'created_by', 'updated_by', 'owned_by',
@@ -56,7 +60,7 @@ public function create(Request $request)
5660
*/
5761
public function read(string $id)
5862
{
59-
$book = Book::visible()->findOrFail($id);
63+
$book = $this->queries->findVisibleByIdOrFail(intval($id));
6064
$book = $this->forJsonDisplay($book);
6165
$book->load(['createdBy', 'updatedBy', 'ownedBy']);
6266

@@ -83,7 +87,7 @@ public function read(string $id)
8387
*/
8488
public function update(Request $request, string $id)
8589
{
86-
$book = Book::visible()->findOrFail($id);
90+
$book = $this->queries->findVisibleByIdOrFail(intval($id));
8791
$this->checkOwnablePermission('book-update', $book);
8892

8993
$requestData = $this->validate($request, $this->rules()['update']);
@@ -100,7 +104,7 @@ public function update(Request $request, string $id)
100104
*/
101105
public function delete(string $id)
102106
{
103-
$book = Book::visible()->findOrFail($id);
107+
$book = $this->queries->findVisibleByIdOrFail(intval($id));
104108
$this->checkOwnablePermission('book-delete', $book);
105109

106110
$this->bookRepo->destroy($book);

0 commit comments

Comments
 (0)