'boolean', 'show_email' => 'boolean', 'show_joined_date' => 'boolean', 'allow_comments' => 'boolean', 'is_banned' => 'boolean', 'upload_restricted' => 'boolean', 'comment_restricted' => 'boolean', 'profile_edit_restricted' => 'boolean', 'metadata' => 'array', ]; /** * Boot the model */ protected static function boot() { parent::boot(); // Handle cascading delete for associated data static::deleting(function ($profile) { // Delete comments on this profile $profile->comments()->delete(); // Delete profile comments made by this user ProfileComment::where('user_id', $profile->user_id)->delete(); // Delete messages sent by this user Message::where('sender_id', $profile->user_id)->delete(); // Delete reactions made by this user $profile->reactions()->delete(); // Delete avatar and banner files if they exist if ($profile->avatar_path) { Storage::disk('local')->delete($profile->avatar_path); } if ($profile->banner_path) { Storage::disk('local')->delete($profile->banner_path); } }); } /** * Get the user that owns the profile */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * Get all comments for this profile */ public function comments(): HasMany { return $this->hasMany(ProfileComment::class)->orderBy('created_at', 'desc'); } /** * Get approved comments for this profile */ public function approvedComments(): HasMany { return $this->hasMany(ProfileComment::class) ->where('approved', true) ->orderBy('created_at', 'desc'); } /** * Get the avatar URL */ public function getAvatarUrlAttribute(): ?string { if ($this->avatar_path) { return Storage::disk('public')->url($this->avatar_path); } // Return default avatar or gravatar if ($this->user && $this->user->email) { $hash = md5(strtolower(trim($this->user->email))); return "https://www.gravatar.com/avatar/{$hash}?d=identicon&s=150"; } return null; } /** * Get the banner URL */ public function getBannerUrlAttribute(): ?string { if ($this->banner_path) { return Storage::disk('public')->url($this->banner_path); } return null; } /** * Get display name or fallback to user name */ public function getDisplayNameAttribute($value): string { return $value ?: ($this->user->name ?? 'Anonymous'); } /** * Check if profile is viewable by current user */ public function isViewableBy(?User $user = null): bool { // If profile is private, only allow specific access if (!$this->is_public) { // Guest users cannot view private profiles if (!$user) { return false; } // Owner can always view their own profile if ($user->id === $this->user_id) { return true; } // Admins can view all profiles (users with all permissions or specific admin permissions) if ($user->hasPermission('*') || $user->hasPermission('socialbase.profiles.view')) { return true; } // Private profile, not owner, not admin - deny access return false; } // Profile is public - allow access to everyone (including guests) return true; } /** * Check if comments are allowed on this profile */ public function allowsComments(): bool { return $this->allow_comments; } /** * Scope to get public profiles only */ public function scopePublic($query) { return $query->where('is_public', true); } /** * Get profile statistics */ public function getStatsAttribute(): array { return [ 'comments_count' => $this->comments()->count(), 'approved_comments_count' => $this->approvedComments()->count(), 'joined_date' => $this->user->created_at ?? null, ]; } /** * Check if user can upload files */ public function canUpload(): bool { return !$this->upload_restricted && !$this->is_banned && $this->restriction_level !== 'banned'; } /** * Check if user can comment */ public function canComment(): bool { return !$this->comment_restricted && !$this->is_banned && $this->restriction_level !== 'banned'; } /** * Check if user can edit profile */ public function canEditProfile(): bool { return !$this->profile_edit_restricted && !$this->is_banned && $this->restriction_level !== 'banned'; } /** * Check if user has any restrictions */ public function hasRestrictions(): bool { return $this->is_banned || $this->upload_restricted || $this->comment_restricted || $this->profile_edit_restricted || $this->restriction_level !== 'none'; } /** * Get restriction status text */ public function getRestrictionStatusAttribute(): string { if ($this->is_banned) { return 'Banned'; } switch ($this->restriction_level) { case 'warning': return 'Warning'; case 'limited': return 'Limited'; case 'suspended': return 'Suspended'; case 'banned': return 'Banned'; default: return $this->hasRestrictions() ? 'Restricted' : 'Active'; } } /** * Helper method to get existing profile */ public static function getForUser(int $userId): ?UserProfile { // First try to find existing profile (including soft deleted) $profile = static::withTrashed()->where('user_id', $userId)->first(); if ($profile) { // If it's soft deleted, restore it if ($profile->trashed()) { $profile->restore(); } return $profile; } return null; } /** * Helper method to create profile with default values * Only use this when user explicitly wants to create a profile */ public static function createForUser(int $userId): UserProfile { return static::create([ 'user_id' => $userId, 'is_public' => false, // Private by default until setup 'restriction_level' => 'none', 'show_email' => false, 'show_joined_date' => true, 'allow_comments' => true, ]); } }