Wire admin studio SSR and search infrastructure
This commit is contained in:
@@ -55,7 +55,7 @@ final class ArtworkSearchService
|
||||
}
|
||||
|
||||
if (! empty($filters['category'])) {
|
||||
$filterParts[] = 'category = "' . addslashes((string) $filters['category']) . '"';
|
||||
$filterParts[] = $this->categoryFilterClause((string) $filters['category']);
|
||||
}
|
||||
|
||||
if (! empty($filters['orientation'])) {
|
||||
@@ -90,7 +90,7 @@ final class ArtworkSearchService
|
||||
return $results;
|
||||
}
|
||||
|
||||
$page = max(1, (int) request()->get('page', 1));
|
||||
$page = $this->currentPage();
|
||||
$candidateCount = $this->determineSearchCandidatePoolSize($perPage, $page);
|
||||
$fallbackResults = Artwork::search($q ?: '')
|
||||
->options($options)
|
||||
@@ -108,7 +108,7 @@ final class ArtworkSearchService
|
||||
|
||||
public function searchWithThumbnailPreference(array $options, int $perPage, bool $excludeMissing = false, ?int $page = null): LengthAwarePaginator
|
||||
{
|
||||
$page = max(1, $page ?? (int) request()->get('page', 1));
|
||||
$page = max(1, $page ?? $this->currentPage());
|
||||
$candidateCount = $this->determineSearchCandidatePoolSize($perPage, $page);
|
||||
$results = Artwork::search('')
|
||||
->options($this->viewerAwareOptions($options))
|
||||
@@ -139,7 +139,7 @@ final class ArtworkSearchService
|
||||
}
|
||||
|
||||
$sort = in_array($sort, self::TAG_SORTS, true) ? $sort : 'popular';
|
||||
$cacheKey = "search.tag.{$slug}.{$sort}.{$perPage}.{$this->viewerCacheSegment()}.page." . request()->get('page', 1);
|
||||
$cacheKey = "search.tag.{$slug}.{$sort}.{$perPage}.{$this->viewerCacheSegment()}.page." . $this->currentPage();
|
||||
|
||||
return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($tag, $perPage, $sort) {
|
||||
$query = Artwork::query()
|
||||
@@ -180,12 +180,12 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function byCategory(string $cat, int $perPage = 24, array $filters = []): LengthAwarePaginator
|
||||
{
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
$cacheKey = "search.cat.catalog-visible.v2.{$cat}.{$this->viewerCacheSegment()}.page." . $page;
|
||||
|
||||
return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($cat, $perPage, $page) {
|
||||
return $this->searchWithThumbnailPreference([
|
||||
'filter' => self::BASE_FILTER . ' AND category = "' . addslashes($cat) . '"',
|
||||
'filter' => self::BASE_FILTER . ' AND ' . $this->categoryFilterClause($cat),
|
||||
'sort' => ['created_at:desc'],
|
||||
], $perPage, false, $page);
|
||||
});
|
||||
@@ -226,15 +226,15 @@ final class ArtworkSearchService
|
||||
public function categoryPageSort(string $categorySlug, string $sort = 'trending', int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
$sort = array_key_exists($sort, self::CATEGORY_SORT_FIELDS) ? $sort : 'trending';
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
$ttl = self::CATEGORY_SORT_TTL[$sort] ?? self::CACHE_TTL;
|
||||
$cacheKey = "category.catalog-visible.v2.{$categorySlug}.{$sort}.{$this->viewerCacheSegment()}.{$page}";
|
||||
|
||||
return Cache::remember($cacheKey, $ttl, function () use ($categorySlug, $sort, $perPage) {
|
||||
return $this->searchWithThumbnailPreference([
|
||||
'filter' => self::BASE_FILTER . ' AND category = "' . addslashes($categorySlug) . '"',
|
||||
'filter' => self::BASE_FILTER . ' AND ' . $this->categoryFilterClause($categorySlug),
|
||||
'sort' => self::CATEGORY_SORT_FIELDS[$sort],
|
||||
], $perPage, false, (int) request()->get('page', 1));
|
||||
], $perPage, false, $this->currentPage());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -247,15 +247,15 @@ final class ArtworkSearchService
|
||||
public function contentTypePageSort(string $contentTypeSlug, string $sort = 'trending', int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
$sort = array_key_exists($sort, self::CATEGORY_SORT_FIELDS) ? $sort : 'trending';
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
$ttl = self::CATEGORY_SORT_TTL[$sort] ?? self::CACHE_TTL;
|
||||
$cacheKey = "content_type.catalog-visible.v2.{$contentTypeSlug}.{$sort}.{$this->viewerCacheSegment()}.{$page}";
|
||||
|
||||
return Cache::remember($cacheKey, $ttl, function () use ($contentTypeSlug, $sort, $perPage) {
|
||||
return $this->searchWithThumbnailPreference([
|
||||
'filter' => self::BASE_FILTER . ' AND content_type = "' . addslashes($contentTypeSlug) . '"',
|
||||
'filter' => self::BASE_FILTER . ' AND ' . $this->contentTypeFilterClause($contentTypeSlug),
|
||||
'sort' => self::CATEGORY_SORT_FIELDS[$sort],
|
||||
], $perPage, false, (int) request()->get('page', 1));
|
||||
], $perPage, false, $this->currentPage());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function popular(int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
return Cache::remember('search.popular.' . $this->viewerCacheSegment() . '.page.' . request()->get('page', 1), self::CACHE_TTL, function () use ($perPage) {
|
||||
return Cache::remember('search.popular.' . $this->viewerCacheSegment() . '.page.' . $this->currentPage(), self::CACHE_TTL, function () use ($perPage) {
|
||||
return Artwork::search('')
|
||||
->options($this->viewerAwareOptions([
|
||||
'filter' => self::BASE_FILTER,
|
||||
@@ -310,7 +310,7 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function recent(int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
return Cache::remember('search.recent.' . $this->viewerCacheSegment() . '.page.' . request()->get('page', 1), self::CACHE_TTL, function () use ($perPage) {
|
||||
return Cache::remember('search.recent.' . $this->viewerCacheSegment() . '.page.' . $this->currentPage(), self::CACHE_TTL, function () use ($perPage) {
|
||||
return Artwork::search('')
|
||||
->options($this->viewerAwareOptions([
|
||||
'filter' => self::BASE_FILTER,
|
||||
@@ -330,7 +330,7 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function discoverTrending(int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
$windowDays = $this->timeWindow->getTrendingWindowDays(30);
|
||||
$cutoff = now()->subDays($windowDays)->toDateString();
|
||||
// Include window in cache key so adaptive expansions surface immediately
|
||||
@@ -352,7 +352,7 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function discoverRising(int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
$windowDays = $this->timeWindow->getTrendingWindowDays(30);
|
||||
$cutoff = now()->subDays($windowDays)->toDateString();
|
||||
$cacheKey = "discover.rising.{$windowDays}d.{$this->viewerCacheSegment()}.{$page}";
|
||||
@@ -370,7 +370,7 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function discoverFresh(int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
return Cache::remember("discover.fresh.{$this->viewerCacheSegment()}.{$page}", self::CACHE_TTL, function () use ($perPage) {
|
||||
return $this->searchWithThumbnailPreference([
|
||||
'filter' => self::BASE_FILTER,
|
||||
@@ -384,7 +384,7 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function discoverTopRated(int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
return Cache::remember("discover.top-rated.{$this->viewerCacheSegment()}.{$page}", self::CACHE_TTL, function () use ($perPage) {
|
||||
return $this->searchWithThumbnailPreference([
|
||||
'filter' => self::BASE_FILTER,
|
||||
@@ -398,7 +398,7 @@ final class ArtworkSearchService
|
||||
*/
|
||||
public function discoverMostDownloaded(int $perPage = 24): LengthAwarePaginator
|
||||
{
|
||||
$page = (int) request()->get('page', 1);
|
||||
$page = $this->currentPage();
|
||||
return Cache::remember("discover.most-downloaded.{$this->viewerCacheSegment()}.{$page}", self::CACHE_TTL, function () use ($perPage) {
|
||||
return $this->searchWithThumbnailPreference([
|
||||
'filter' => self::BASE_FILTER,
|
||||
@@ -441,6 +441,11 @@ final class ArtworkSearchService
|
||||
return $options;
|
||||
}
|
||||
|
||||
private function currentPage(): int
|
||||
{
|
||||
return max(1, (int) request()->query('page', 1));
|
||||
}
|
||||
|
||||
private function shouldFallbackToViewerVisibilityFiltering(LengthAwarePaginator $results): bool
|
||||
{
|
||||
if ($results->total() > 0) {
|
||||
@@ -468,7 +473,7 @@ final class ArtworkSearchService
|
||||
}
|
||||
|
||||
$catFilter = implode(' OR ', array_map(
|
||||
fn (string $c): string => 'category = "' . addslashes($c) . '"',
|
||||
fn (string $c): string => $this->categoryFilterClause($c),
|
||||
array_slice($categorySlugs, 0, 3)
|
||||
));
|
||||
|
||||
@@ -494,6 +499,20 @@ final class ArtworkSearchService
|
||||
return in_array($field, $allowed, true) ? [$field, $dir] : [null, 'desc'];
|
||||
}
|
||||
|
||||
private function categoryFilterClause(string $categorySlug): string
|
||||
{
|
||||
$quoted = addslashes($categorySlug);
|
||||
|
||||
return '(category = "' . $quoted . '" OR categories = "' . $quoted . '")';
|
||||
}
|
||||
|
||||
private function contentTypeFilterClause(string $contentTypeSlug): string
|
||||
{
|
||||
$quoted = addslashes($contentTypeSlug);
|
||||
|
||||
return '(content_type = "' . $quoted . '" OR content_types = "' . $quoted . '")';
|
||||
}
|
||||
|
||||
private function rerankSearchCollectionByThumbnailHealth(Collection $items, bool $excludeMissing): Collection
|
||||
{
|
||||
if ($items->isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user