storing analytics data
This commit is contained in:
93
app/Services/UserPreferenceService.php
Normal file
93
app/Services/UserPreferenceService.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* UserPreferenceService
|
||||
*
|
||||
* Builds a lightweight preference profile for a user based on:
|
||||
* - Tags on artworks they have favourited
|
||||
* - Categories of artwork they have favourited / downloaded
|
||||
* - Creators they follow
|
||||
*
|
||||
* Output shape:
|
||||
* [
|
||||
* 'top_tags' => ['space', 'nature', ...], // up to 5 slugs
|
||||
* 'top_categories' => ['wallpapers', ...], // up to 3 slugs
|
||||
* 'followed_creators' => [1, 5, 23, ...], // user IDs
|
||||
* ]
|
||||
*/
|
||||
final class UserPreferenceService
|
||||
{
|
||||
private const CACHE_TTL = 300; // 5 minutes
|
||||
|
||||
public function build(User $user): array
|
||||
{
|
||||
return Cache::remember(
|
||||
"user.prefs.{$user->id}",
|
||||
self::CACHE_TTL,
|
||||
fn () => $this->compute($user)
|
||||
);
|
||||
}
|
||||
|
||||
private function compute(User $user): array
|
||||
{
|
||||
return [
|
||||
'top_tags' => $this->topTags($user),
|
||||
'top_categories' => $this->topCategories($user),
|
||||
'followed_creators' => $this->followedCreatorIds($user),
|
||||
];
|
||||
}
|
||||
|
||||
/** Top tag slugs derived from the user's favourited artworks */
|
||||
private function topTags(User $user, int $limit = 5): array
|
||||
{
|
||||
return DB::table('artwork_favourites as af')
|
||||
->join('artwork_tag as at', 'at.artwork_id', '=', 'af.artwork_id')
|
||||
->join('tags as t', 't.id', '=', 'at.tag_id')
|
||||
->where('af.user_id', $user->id)
|
||||
->where('t.is_active', true)
|
||||
->selectRaw('t.slug, COUNT(*) as cnt')
|
||||
->groupBy('t.id', 't.slug')
|
||||
->orderByDesc('cnt')
|
||||
->limit($limit)
|
||||
->pluck('slug')
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
/** Top category slugs derived from the user's favourited artworks */
|
||||
private function topCategories(User $user, int $limit = 3): array
|
||||
{
|
||||
return DB::table('artwork_favourites as af')
|
||||
->join('artwork_category as ac', 'ac.artwork_id', '=', 'af.artwork_id')
|
||||
->join('categories as c', 'c.id', '=', 'ac.category_id')
|
||||
->where('af.user_id', $user->id)
|
||||
->whereNull('c.deleted_at')
|
||||
->selectRaw('c.slug, COUNT(*) as cnt')
|
||||
->groupBy('c.id', 'c.slug')
|
||||
->orderByDesc('cnt')
|
||||
->limit($limit)
|
||||
->pluck('slug')
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
|
||||
/** IDs of creators the user follows, latest follows first */
|
||||
private function followedCreatorIds(User $user, int $limit = 100): array
|
||||
{
|
||||
return DB::table('user_followers')
|
||||
->where('follower_id', $user->id)
|
||||
->orderByDesc('created_at')
|
||||
->limit($limit)
|
||||
->pluck('user_id')
|
||||
->values()
|
||||
->all();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user