*/ protected $fillable = [ 'username', 'email', 'alias', 'password_hash', 'first_name', 'last_name', 'bio', 'profile_picture_url' ]; /** * The attributes that should be hidden for serialization. * * @var array */ protected $hidden = [ 'password_hash', 'remember_token', ]; /** * The attributes that should be cast. * * @var array */ protected $casts = [ 'email_verified_at' => 'datetime', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; /** * Get the password for the user (Laravel Auth compatibility). */ public function getAuthPassword() { return $this->password_hash; } /** * Set the password hash when setting password. */ public function setPasswordAttribute($password) { $this->attributes['password_hash'] = bcrypt($password); } /** * Get the user's full name. */ public function getFullNameAttribute(): string { return trim($this->first_name . ' ' . $this->last_name); } /** * Scope pour rechercher par nom d'utilisateur ou email. */ public function scopeSearch($query, $search) { return $query->where('username', 'like', "%{$search}%") ->orWhere('email', 'like', "%{$search}%") ->orWhere('first_name', 'like', "%{$search}%") ->orWhere('last_name', 'like', "%{$search}%"); } // ===== RELATIONS ===== /** * Galeries possédées par cet utilisateur. */ public function ownedGalleries() { return $this->hasMany(Gallery::class, 'owner_id'); } /** * Œuvres créées par cet utilisateur. */ public function artworks() { return $this->hasMany(Artwork::class, 'creator_id'); } /** * Galeries auxquelles cet utilisateur a accès (invitations). */ public function galleryMemberships() { return $this->hasMany(GalleryMember::class, 'user_id'); } /** * Galeries auxquelles l'utilisateur a accès avec statut accepté. */ public function accessibleGalleries() { return $this->belongsToMany(Gallery::class, 'gallery_members', 'user_id', 'gallery_id') ->wherePivot('status', 'accepted') ->withPivot(['role', 'status', 'invited_at', 'updated_at']); } /** * Invitations en attente pour cet utilisateur. */ public function pendingInvitations() { return $this->belongsToMany(Gallery::class, 'gallery_members', 'user_id', 'gallery_id') ->wherePivot('status', 'pending') ->withPivot(['role', 'status', 'invited_at', 'updated_at']); } /** * Vérifier si l'utilisateur peut accéder à une galerie. */ public function canAccessGallery($galleryId): bool { // Propriétaire de la galerie if ($this->ownedGalleries()->where('id', $galleryId)->exists()) { return true; } // Membre avec accès accepté return $this->galleryMemberships() ->where('gallery_id', $galleryId) ->where('status', 'accepted') ->exists(); } /** * Vérifier si l'utilisateur peut éditer une galerie. */ public function canEditGallery($galleryId): bool { // Propriétaire if ($this->ownedGalleries()->where('id', $galleryId)->exists()) { return true; } // Membre avec rôle editor return $this->galleryMemberships() ->where('gallery_id', $galleryId) ->where('status', 'accepted') ->where('role', 'editor') ->exists(); } /** * Obtenir le rôle de l'utilisateur dans une galerie. */ public function getRoleInGallery($galleryId): ?string { // Propriétaire if ($this->ownedGalleries()->where('id', $galleryId)->exists()) { return 'owner'; } // Membre $membership = $this->galleryMemberships() ->where('gallery_id', $galleryId) ->where('status', 'accepted') ->first(); return $membership ? $membership->role : null; } /** * Statistiques de l'utilisateur. */ public function getStatsAttribute(): array { return [ 'galleries_count' => $this->ownedGalleries()->count(), 'artworks_count' => $this->artworks()->count(), 'public_galleries_count' => $this->ownedGalleries()->where('is_public', true)->count(), 'artworks_for_sale_count' => $this->artworks()->where('is_for_sale', true)->count(), ]; } }