303 lines
8.2 KiB
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,
|
|
]);
|
|
}
|
|
} |