Files
Virtnet.bond/extensions/Others/SocialBase/Models/UserProfile.php

303 lines
8.2 KiB
PHP

<?php
namespace Paymenter\Extensions\Others\SocialBase\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Storage;
use App\Models\User;
use Paymenter\Extensions\Others\SocialBase\Traits\HasReactions;
use Paymenter\Extensions\Others\SocialBase\Models\Message;
use Paymenter\Extensions\Others\SocialBase\Models\ProfileComment;
class UserProfile extends Model
{
use SoftDeletes, HasReactions;
protected $table = 'ext_social_user_profiles';
protected $fillable = [
'user_id',
'display_name',
'bio',
'location',
'website',
'avatar_path',
'banner_path',
'is_public',
'show_email',
'show_joined_date',
'allow_comments',
'is_banned',
'upload_restricted',
'comment_restricted',
'profile_edit_restricted',
'restriction_reason',
'restriction_level',
'theme',
'metadata',
'moderation_status',
'moderation_notes',
];
protected $casts = [
'is_public' => '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,
]);
}
}