Files
SkinbaseNova/.deploy/artwork-evolution-release/app/Models/UserRecoProfile.php
2026-04-18 17:02:56 +02:00

74 lines
2.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Models;
use App\DTOs\UserRecoProfileDTO;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* Persisted cache of a user's recommendation preference profile.
*
* Schema: user_reco_profiles (user_id PK, json columns, timestamps).
* Rebuilt by UserPreferenceBuilder → stale when updated_at < now() - TTL.
*/
class UserRecoProfile extends Model
{
protected $table = 'user_reco_profiles';
protected $primaryKey = 'user_id';
public $incrementing = false;
protected $keyType = 'int';
protected $guarded = [];
protected $casts = [
'top_tags_json' => 'array',
'top_categories_json' => 'array',
'followed_creator_ids_json' => 'array',
'tag_weights_json' => 'array',
'category_weights_json' => 'array',
'disliked_tag_ids_json' => 'array',
];
// ── Relations ─────────────────────────────────────────────────────────────
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
// ── Helpers ───────────────────────────────────────────────────────────────
/**
* Hydrate a DTO from this model's JSON columns.
*/
public function toDTO(): UserRecoProfileDTO
{
return new UserRecoProfileDTO(
topTagSlugs: (array) ($this->top_tags_json ?? []),
topCategorySlugs: (array) ($this->top_categories_json ?? []),
strongCreatorIds: array_map('intval', (array) ($this->followed_creator_ids_json ?? [])),
tagWeights: array_map('floatval', (array) ($this->tag_weights_json ?? [])),
categoryWeights: array_map('floatval', (array) ($this->category_weights_json ?? [])),
dislikedTagSlugs: (array) ($this->disliked_tag_ids_json ?? []),
);
}
/**
* True when the stored profile is still within the configured TTL.
*/
public function isFresh(): bool
{
if ($this->updated_at === null) {
return false;
}
$ttl = (int) config('recommendations.ttl.user_reco_profile', 6 * 3600);
return $this->updated_at->addSeconds($ttl)->isFuture();
}
}