*/ protected $fillable = [ 'name', 'email', 'password', 'role', 'theme_preference', 'pending_email', ]; /** * The attributes that should be hidden for serialization. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', 'role' => UserRole::class, 'theme_preference' => ThemePreference::class, 'is_banned' => 'boolean', 'ban_date' => 'datetime', ]; } /** * Get the user's profile */ public function profile(): HasOne { return $this->hasOne(Profile::class); } /** * Get the user's display name, falling back to username if not set */ public function getDisplayName(): string { return $this->profile?->display_name ?? $this->name; } /** * Check if the user has moderation privileges */ public function canModerate(): bool { return $this->role->canModerate(); } /** * Check if the user has admin privileges */ public function canAdmin(): bool { return $this->role->canAdmin(); } /** * Ban the user with a reason */ public function ban(string $reason): void { $this->update([ 'is_banned' => true, 'ban_reason' => $reason, 'ban_date' => now(), ]); } /** * Unban the user */ public function unban(): void { $this->update([ 'is_banned' => false, 'ban_reason' => null, 'ban_date' => null, ]); } /** * Handle pending email changes */ public function setPendingEmail(string $email): void { $this->update(['pending_email' => $email]); } /** * Confirm pending email change */ public function confirmEmailChange(): void { if ($this->pending_email) { $this->update([ 'email' => $this->pending_email, 'pending_email' => null, ]); } } /** * Boot the model */ protected static function boot() { parent::boot(); static::creating(function (User $user) { if (!$user->user_id) { $user->user_id = IdGenerator::generate(User::class, 'user_id'); } if (!$user->role) { $user->role = UserRole::USER; } if (!$user->theme_preference) { $user->theme_preference = ThemePreference::LIGHT; } }); } }