*/ use Billable, HasFactory, HasMedia, HasUuids, HasWorkspace, Notifiable; /** * The attributes that are mass assignable. * * @var list */ protected $fillable = [ 'name', 'email', 'password', 'setup', 'persona', 'current_workspace_id', 'email_verified_at', ]; /** * The attributes that should be hidden for serialization. * * @var list */ protected $hidden = [ 'password', 'two_factor_secret', 'two_factor_recovery_codes', 'remember_token', ]; protected $appends = [ 'has_photo', 'photo_url', ]; public function getHasPhotoAttribute(): bool { return $this->getFirstMedia('avatar') !== null; } public function getPhotoUrlAttribute(): ?string { return $this->getFirstMediaUrl('avatar'); } /** * Get the attributes that should be cast. * * @return array */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', 'two_factor_confirmed_at' => 'datetime', 'setup' => Setup::class, 'persona' => Persona::class, ]; } /** * @return HasMany */ public function notifications(): HasMany { return $this->hasMany(Notification::class); } public function notificationPreference(): HasOne { return $this->hasOne(NotificationPreference::class); } public function wantsEmailFor(string $type): bool { $preference = $this->notificationPreference; if (! $preference) { return true; // Default: all enabled } return match ($type) { 'post_published' => $preference->post_published, 'post_failed', 'post_partially_published' => $preference->post_failed, 'account_disconnected' => $preference->account_disconnected, default => true, }; } /** * Check if user has an active subscription. * In self-hosted mode, always returns true (no subscription required). */ public function hasActiveSubscription(): bool { if (config('trypost.self_hosted')) { return true; } return $this->subscribed('default'); } /** * Check if user has ever had a subscription (for trial eligibility). */ public function hasEverSubscribed(): bool { return $this->subscriptions()->exists(); } }