Queries: Updated old use-specific entity query classes
- Updated name to align, and differentate from new 'XQueries' clases. - Removed old sketchy base class with app resolving workarounds, to a proper injection-based approach. - Also fixed wrong translation text used in PageQueries.
This commit is contained in:
parent
b77ab6f3af
commit
ed21a6d798
10 changed files with 57 additions and 83 deletions
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace BookStack\Activity\Controllers;
|
||||
|
||||
use BookStack\Entities\Queries\TopFavourites;
|
||||
use BookStack\Entities\Queries\QueryTopFavourites;
|
||||
use BookStack\Entities\Tools\MixedEntityRequestHelper;
|
||||
use BookStack\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
@ -21,7 +21,7 @@ class FavouriteController extends Controller
|
|||
{
|
||||
$viewCount = 20;
|
||||
$page = intval($request->get('page', 1));
|
||||
$favourites = (new TopFavourites())->run($viewCount + 1, (($page - 1) * $viewCount));
|
||||
$favourites = (new QueryTopFavourites())->run($viewCount + 1, (($page - 1) * $viewCount));
|
||||
|
||||
$hasMoreLink = ($favourites->count() > $viewCount) ? url('/favourites?page=' . ($page + 1)) : null;
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ namespace BookStack\App;
|
|||
use BookStack\Activity\ActivityQueries;
|
||||
use BookStack\Entities\Models\Page;
|
||||
use BookStack\Entities\Queries\EntityQueries;
|
||||
use BookStack\Entities\Queries\RecentlyViewed;
|
||||
use BookStack\Entities\Queries\TopFavourites;
|
||||
use BookStack\Entities\Queries\QueryRecentlyViewed;
|
||||
use BookStack\Entities\Queries\QueryTopFavourites;
|
||||
use BookStack\Entities\Tools\PageContent;
|
||||
use BookStack\Http\Controller;
|
||||
use BookStack\Uploads\FaviconHandler;
|
||||
|
@ -23,8 +23,12 @@ class HomeController extends Controller
|
|||
/**
|
||||
* Display the homepage.
|
||||
*/
|
||||
public function index(Request $request, ActivityQueries $activities)
|
||||
{
|
||||
public function index(
|
||||
Request $request,
|
||||
ActivityQueries $activities,
|
||||
QueryRecentlyViewed $recentlyViewed,
|
||||
QueryTopFavourites $topFavourites,
|
||||
) {
|
||||
$activity = $activities->latest(10);
|
||||
$draftPages = [];
|
||||
|
||||
|
@ -38,9 +42,9 @@ class HomeController extends Controller
|
|||
|
||||
$recentFactor = count($draftPages) > 0 ? 0.5 : 1;
|
||||
$recents = $this->isSignedIn() ?
|
||||
(new RecentlyViewed())->run(12 * $recentFactor, 1)
|
||||
$recentlyViewed->run(12 * $recentFactor, 1)
|
||||
: $this->queries->books->visibleForList()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get();
|
||||
$favourites = (new TopFavourites())->run(6);
|
||||
$favourites = $topFavourites->run(6);
|
||||
$recentlyUpdatedPages = $this->queries->pages->visibleForList()
|
||||
->where('draft', false)
|
||||
->orderBy('updated_at', 'desc')
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace BookStack\Entities\Queries;
|
||||
|
||||
use BookStack\Entities\EntityProvider;
|
||||
use BookStack\Entities\Tools\MixedEntityListLoader;
|
||||
use BookStack\Permissions\PermissionApplicator;
|
||||
|
||||
abstract class EntityQuery
|
||||
{
|
||||
protected function mixedEntityListLoader(): MixedEntityListLoader
|
||||
{
|
||||
return app()->make(MixedEntityListLoader::class);
|
||||
}
|
||||
|
||||
protected function permissionService(): PermissionApplicator
|
||||
{
|
||||
return app()->make(PermissionApplicator::class);
|
||||
}
|
||||
|
||||
protected function entityProvider(): EntityProvider
|
||||
{
|
||||
return app()->make(EntityProvider::class);
|
||||
}
|
||||
}
|
|
@ -50,7 +50,7 @@ class PageQueries implements ProvidesEntityQueries
|
|||
->first();
|
||||
|
||||
if (is_null($page)) {
|
||||
throw new NotFoundException(trans('errors.chapter_not_found'));
|
||||
throw new NotFoundException(trans('errors.page_not_found'));
|
||||
}
|
||||
|
||||
return $page;
|
||||
|
|
|
@ -3,24 +3,32 @@
|
|||
namespace BookStack\Entities\Queries;
|
||||
|
||||
use BookStack\Activity\Models\View;
|
||||
use BookStack\Entities\EntityProvider;
|
||||
use BookStack\Entities\Models\BookChild;
|
||||
use BookStack\Entities\Models\Entity;
|
||||
use BookStack\Permissions\PermissionApplicator;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Popular extends EntityQuery
|
||||
class QueryPopular
|
||||
{
|
||||
public function __construct(
|
||||
protected PermissionApplicator $permissions,
|
||||
protected EntityProvider $entityProvider,
|
||||
) {
|
||||
}
|
||||
|
||||
public function run(int $count, int $page, array $filterModels = null)
|
||||
{
|
||||
$query = $this->permissionService()
|
||||
$query = $this->permissions
|
||||
->restrictEntityRelationQuery(View::query(), 'views', 'viewable_id', 'viewable_type')
|
||||
->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count'))
|
||||
->groupBy('viewable_id', 'viewable_type')
|
||||
->orderBy('view_count', 'desc');
|
||||
|
||||
if ($filterModels) {
|
||||
$query->whereIn('viewable_type', $this->entityProvider()->getMorphClasses($filterModels));
|
||||
$query->whereIn('viewable_type', $this->entityProvider->getMorphClasses($filterModels));
|
||||
}
|
||||
|
||||
$entities = $query->with('viewable')
|
||||
|
@ -35,7 +43,7 @@ class Popular extends EntityQuery
|
|||
return $entities;
|
||||
}
|
||||
|
||||
protected function loadBooksForChildren(Collection $entities)
|
||||
protected function loadBooksForChildren(Collection $entities): void
|
||||
{
|
||||
$bookChildren = $entities->filter(fn(Entity $entity) => $entity instanceof BookChild);
|
||||
$eloquent = (new \Illuminate\Database\Eloquent\Collection($bookChildren));
|
|
@ -3,10 +3,18 @@
|
|||
namespace BookStack\Entities\Queries;
|
||||
|
||||
use BookStack\Activity\Models\View;
|
||||
use BookStack\Entities\Tools\MixedEntityListLoader;
|
||||
use BookStack\Permissions\PermissionApplicator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class RecentlyViewed extends EntityQuery
|
||||
class QueryRecentlyViewed
|
||||
{
|
||||
public function __construct(
|
||||
protected PermissionApplicator $permissions,
|
||||
protected MixedEntityListLoader $listLoader,
|
||||
) {
|
||||
}
|
||||
|
||||
public function run(int $count, int $page): Collection
|
||||
{
|
||||
$user = user();
|
||||
|
@ -14,7 +22,7 @@ class RecentlyViewed extends EntityQuery
|
|||
return collect();
|
||||
}
|
||||
|
||||
$query = $this->permissionService()->restrictEntityRelationQuery(
|
||||
$query = $this->permissions->restrictEntityRelationQuery(
|
||||
View::query(),
|
||||
'views',
|
||||
'viewable_id',
|
||||
|
@ -28,7 +36,7 @@ class RecentlyViewed extends EntityQuery
|
|||
->take($count)
|
||||
->get();
|
||||
|
||||
$this->mixedEntityListLoader()->loadIntoRelations($views->all(), 'viewable', false);
|
||||
$this->listLoader->loadIntoRelations($views->all(), 'viewable', false);
|
||||
|
||||
return $views->pluck('viewable')->filter();
|
||||
}
|
|
@ -3,10 +3,18 @@
|
|||
namespace BookStack\Entities\Queries;
|
||||
|
||||
use BookStack\Activity\Models\Favourite;
|
||||
use BookStack\Entities\Tools\MixedEntityListLoader;
|
||||
use BookStack\Permissions\PermissionApplicator;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
|
||||
class TopFavourites extends EntityQuery
|
||||
class QueryTopFavourites
|
||||
{
|
||||
public function __construct(
|
||||
protected PermissionApplicator $permissions,
|
||||
protected MixedEntityListLoader $listLoader,
|
||||
) {
|
||||
}
|
||||
|
||||
public function run(int $count, int $skip = 0)
|
||||
{
|
||||
$user = user();
|
||||
|
@ -14,7 +22,7 @@ class TopFavourites extends EntityQuery
|
|||
return collect();
|
||||
}
|
||||
|
||||
$query = $this->permissionService()
|
||||
$query = $this->permissions
|
||||
->restrictEntityRelationQuery(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type')
|
||||
->select('favourites.*')
|
||||
->leftJoin('views', function (JoinClause $join) {
|
||||
|
@ -30,7 +38,7 @@ class TopFavourites extends EntityQuery
|
|||
->take($count)
|
||||
->get();
|
||||
|
||||
$this->mixedEntityListLoader()->loadIntoRelations($favourites->all(), 'favouritable', false);
|
||||
$this->listLoader->loadIntoRelations($favourites->all(), 'favouritable', false);
|
||||
|
||||
return $favourites->pluck('favouritable')->filter();
|
||||
}
|
|
@ -3,20 +3,13 @@
|
|||
namespace BookStack\Entities\Tools;
|
||||
|
||||
use BookStack\App\Model;
|
||||
use BookStack\Entities\EntityProvider;
|
||||
use BookStack\Entities\Queries\EntityQueries;
|
||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||
|
||||
class MixedEntityListLoader
|
||||
{
|
||||
protected array $listAttributes = [
|
||||
'page' => ['id', 'name', 'slug', 'book_id', 'chapter_id', 'text', 'draft'],
|
||||
'chapter' => ['id', 'name', 'slug', 'book_id', 'description'],
|
||||
'book' => ['id', 'name', 'slug', 'description'],
|
||||
'bookshelf' => ['id', 'name', 'slug', 'description'],
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
protected EntityProvider $entityProvider
|
||||
protected EntityQueries $queries,
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -61,14 +54,7 @@ class MixedEntityListLoader
|
|||
$modelMap = [];
|
||||
|
||||
foreach ($idsByType as $type => $ids) {
|
||||
if (!isset($this->listAttributes[$type])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$instance = $this->entityProvider->get($type);
|
||||
$models = $instance->newQuery()
|
||||
->select(array_merge($this->listAttributes[$type], $this->getSubSelectsForQuery($type)))
|
||||
->scopes('visible')
|
||||
$models = $this->queries->visibleForList($type)
|
||||
->whereIn('id', $ids)
|
||||
->with($eagerLoadParents ? $this->getRelationsToEagerLoad($type) : [])
|
||||
->get();
|
||||
|
@ -100,19 +86,4 @@ class MixedEntityListLoader
|
|||
|
||||
return $toLoad;
|
||||
}
|
||||
|
||||
protected function getSubSelectsForQuery(string $type): array
|
||||
{
|
||||
$subSelects = [];
|
||||
|
||||
if ($type === 'chapter' || $type === 'page') {
|
||||
$subSelects['book_slug'] = function ($builder) {
|
||||
$builder->select('slug')
|
||||
->from('books')
|
||||
->whereColumn('books.id', '=', 'book_id');
|
||||
};
|
||||
}
|
||||
|
||||
return $subSelects;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace BookStack\Search;
|
||||
|
||||
use BookStack\Entities\Queries\PageQueries;
|
||||
use BookStack\Entities\Queries\Popular;
|
||||
use BookStack\Entities\Queries\QueryPopular;
|
||||
use BookStack\Entities\Tools\SiblingFetcher;
|
||||
use BookStack\Http\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
@ -67,7 +67,7 @@ class SearchController extends Controller
|
|||
* Search for a list of entities and return a partial HTML response of matching entities.
|
||||
* Returns the most popular entities if no search is provided.
|
||||
*/
|
||||
public function searchForSelector(Request $request)
|
||||
public function searchForSelector(Request $request, QueryPopular $queryPopular)
|
||||
{
|
||||
$entityTypes = $request->filled('types') ? explode(',', $request->get('types')) : ['page', 'chapter', 'book'];
|
||||
$searchTerm = $request->get('term', false);
|
||||
|
@ -78,7 +78,7 @@ class SearchController extends Controller
|
|||
$searchTerm .= ' {type:' . implode('|', $entityTypes) . '}';
|
||||
$entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20)['results'];
|
||||
} else {
|
||||
$entities = (new Popular())->run(20, 0, $entityTypes);
|
||||
$entities = $queryPopular->run(20, 0, $entityTypes);
|
||||
}
|
||||
|
||||
return view('search.parts.entity-selector-list', ['entities' => $entities, 'permission' => $permission]);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
@extends('layouts.simple')
|
||||
|
||||
@inject('popular', \BookStack\Entities\Queries\QueryPopular::class)
|
||||
@section('content')
|
||||
<div class="container mt-l">
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
|||
<div class="card mb-xl">
|
||||
<h3 class="card-title">{{ trans('entities.pages_popular') }}</h3>
|
||||
<div class="px-m">
|
||||
@include('entities.list', ['entities' => (new \BookStack\Entities\Queries\Popular)->run(10, 0, ['page']), 'style' => 'compact'])
|
||||
@include('entities.list', ['entities' => $popular->run(10, 0, ['page']), 'style' => 'compact'])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -36,7 +36,7 @@
|
|||
<div class="card mb-xl">
|
||||
<h3 class="card-title">{{ trans('entities.books_popular') }}</h3>
|
||||
<div class="px-m">
|
||||
@include('entities.list', ['entities' => (new \BookStack\Entities\Queries\Popular)->run(10, 0, ['book']), 'style' => 'compact'])
|
||||
@include('entities.list', ['entities' => $popular->run(10, 0, ['book']), 'style' => 'compact'])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -44,7 +44,7 @@
|
|||
<div class="card mb-xl">
|
||||
<h3 class="card-title">{{ trans('entities.chapters_popular') }}</h3>
|
||||
<div class="px-m">
|
||||
@include('entities.list', ['entities' => (new \BookStack\Entities\Queries\Popular)->run(10, 0, ['chapter']), 'style' => 'compact'])
|
||||
@include('entities.list', ['entities' => $popular->run(10, 0, ['chapter']), 'style' => 'compact'])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue