174 lines
5.7 KiB
PHP
174 lines
5.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Collection;
|
|
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
class CollectionDiscoveryService
|
|
{
|
|
private function publicBaseQuery()
|
|
{
|
|
return Collection::query()
|
|
->publicEligible()
|
|
->with([
|
|
'user:id,username,name',
|
|
'coverArtwork:id,user_id,title,slug,hash,thumb_ext,published_at,is_public,is_approved,deleted_at',
|
|
]);
|
|
}
|
|
|
|
public function publicFeaturedCollections(int $limit = 18): EloquentCollection
|
|
{
|
|
$safeLimit = max(1, min($limit, 30));
|
|
$ttl = (int) config('collections.discovery.featured_cache_seconds', 120);
|
|
$cacheKey = sprintf('collections:featured:%d', $safeLimit);
|
|
|
|
return Cache::remember($cacheKey, $ttl, function () use ($safeLimit): EloquentCollection {
|
|
return $this->publicBaseQuery()
|
|
->featuredPublic()
|
|
->orderByDesc('featured_at')
|
|
->orderByDesc('likes_count')
|
|
->orderByDesc('followers_count')
|
|
->orderByDesc('updated_at')
|
|
->limit($safeLimit)
|
|
->get();
|
|
});
|
|
}
|
|
|
|
public function publicRecentCollections(int $limit = 8): EloquentCollection
|
|
{
|
|
return $this->publicBaseQuery()
|
|
->orderByDesc('published_at')
|
|
->orderByDesc('updated_at')
|
|
->limit(max(1, min($limit, 20)))
|
|
->get();
|
|
}
|
|
|
|
public function publicCollectionsByType(string $type, int $limit = 8): EloquentCollection
|
|
{
|
|
return $this->publicBaseQuery()
|
|
->where('type', $type)
|
|
->orderByDesc('is_featured')
|
|
->orderByDesc('followers_count')
|
|
->orderByDesc('saves_count')
|
|
->limit(max(1, min($limit, 20)))
|
|
->get();
|
|
}
|
|
|
|
public function publicTrendingCollections(int $limit = 12): EloquentCollection
|
|
{
|
|
return $this->publicBaseQuery()
|
|
->orderByRaw('(
|
|
(likes_count * 3)
|
|
+ (followers_count * 4)
|
|
+ (saves_count * 4)
|
|
+ (comments_count * 2)
|
|
+ (views_count * 0.05)
|
|
) desc')
|
|
->orderByDesc('last_activity_at')
|
|
->orderByDesc('published_at')
|
|
->limit(max(1, min($limit, 24)))
|
|
->get();
|
|
}
|
|
|
|
public function publicRecentlyActiveCollections(int $limit = 8): EloquentCollection
|
|
{
|
|
return $this->publicBaseQuery()
|
|
->orderByDesc('last_activity_at')
|
|
->orderByDesc('updated_at')
|
|
->limit(max(1, min($limit, 20)))
|
|
->get();
|
|
}
|
|
|
|
public function publicSeasonalCollections(int $limit = 12): EloquentCollection
|
|
{
|
|
return $this->publicBaseQuery()
|
|
->where(function ($query): void {
|
|
$query->whereNotNull('event_key')
|
|
->orWhereNotNull('season_key');
|
|
})
|
|
->orderByDesc('is_featured')
|
|
->orderByDesc('published_at')
|
|
->orderByDesc('updated_at')
|
|
->limit(max(1, min($limit, 24)))
|
|
->get();
|
|
}
|
|
|
|
public function publicCampaignCollections(string $campaignKey, int $limit = 18): EloquentCollection
|
|
{
|
|
$normalizedKey = trim($campaignKey);
|
|
|
|
return $this->publicBaseQuery()
|
|
->where('campaign_key', $normalizedKey)
|
|
->orderByDesc('is_featured')
|
|
->orderByDesc('ranking_score')
|
|
->orderByDesc('followers_count')
|
|
->orderByDesc('updated_at')
|
|
->limit(max(1, min($limit, 30)))
|
|
->get();
|
|
}
|
|
|
|
public function publicCampaignCollectionsByType(string $campaignKey, string $type, int $limit = 8): EloquentCollection
|
|
{
|
|
$normalizedKey = trim($campaignKey);
|
|
|
|
return $this->publicBaseQuery()
|
|
->where('campaign_key', $normalizedKey)
|
|
->where('type', $type)
|
|
->orderByDesc('is_featured')
|
|
->orderByDesc('ranking_score')
|
|
->orderByDesc('updated_at')
|
|
->limit(max(1, min($limit, 20)))
|
|
->get();
|
|
}
|
|
|
|
public function publicTrendingCampaignCollections(string $campaignKey, int $limit = 8): EloquentCollection
|
|
{
|
|
$normalizedKey = trim($campaignKey);
|
|
|
|
return $this->publicBaseQuery()
|
|
->where('campaign_key', $normalizedKey)
|
|
->orderByRaw('(
|
|
(likes_count * 3)
|
|
+ (followers_count * 4)
|
|
+ (saves_count * 4)
|
|
+ (comments_count * 2)
|
|
+ (views_count * 0.05)
|
|
) desc')
|
|
->orderByDesc('last_activity_at')
|
|
->orderByDesc('published_at')
|
|
->limit(max(1, min($limit, 20)))
|
|
->get();
|
|
}
|
|
|
|
public function publicRecentCampaignCollections(string $campaignKey, int $limit = 8): EloquentCollection
|
|
{
|
|
$normalizedKey = trim($campaignKey);
|
|
|
|
return $this->publicBaseQuery()
|
|
->where('campaign_key', $normalizedKey)
|
|
->orderByDesc('published_at')
|
|
->orderByDesc('updated_at')
|
|
->limit(max(1, min($limit, 20)))
|
|
->get();
|
|
}
|
|
|
|
public function relatedPublicCollections(Collection $collection, int $limit = 4): EloquentCollection
|
|
{
|
|
return $this->publicBaseQuery()
|
|
->where('id', '!=', $collection->id)
|
|
->where(function ($query) use ($collection): void {
|
|
$query->where('type', $collection->type)
|
|
->orWhere('user_id', $collection->user_id);
|
|
})
|
|
->orderByDesc('followers_count')
|
|
->orderByDesc('saves_count')
|
|
->orderByDesc('updated_at')
|
|
->limit(max(1, min($limit, 12)))
|
|
->get();
|
|
}
|
|
}
|