Skip to content

Commit

Permalink
fix: refactor Comment, User, UserSocial and Vote models
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiorodriguesroque committed Nov 9, 2024
1 parent 4a64967 commit 48c4fff
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 24 deletions.
54 changes: 47 additions & 7 deletions app/Models/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
namespace App\Models;

use App\Traits\HasUpvote;
use Database\Factories\CommentFactory;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Spatie\Activitylog\LogOptions;
use Xetaio\Mentions\Models\Mention;
use Illuminate\Database\Eloquent\Model;
Expand All @@ -12,6 +17,7 @@

class Comment extends Model
{
/** @use HasFactory<CommentFactory> */
use HasFactory, HasMentionsTrait, LogsActivity, HasUpvote;

public $fillable = [
Expand All @@ -25,29 +31,57 @@ class Comment extends Model
'private' => 'boolean',
];

protected static $recordEvents = ['updated'];
/**
* @var string[] $recordEvents
*/
protected static array $recordEvents = ['updated'];

public function user()
/**
* Get the user that owns the comment.
*
* @return BelongsTo<User, $this>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}

public function item()
/**
* Get the item that owns the comment.
*
* @return BelongsTo<Item, $this>
*/
public function item(): BelongsTo
{
return $this->belongsTo(Item::class);
}

public function parent()
/**
* Get the parent comment.
*
* @return BelongsTo<Comment, $this>
*/
public function parent(): BelongsTo
{
return $this->belongsTo(Comment::class, 'parent_id');
}

public function comments()
/**
* Get the child comments.
*
* @return HasMany<Comment, $this>
*/
public function comments(): HasMany
{
return $this->hasMany(Comment::class, 'parent_id');
}

public function mentions()
/**
* Get the comment mentions.
*
* @return MorphMany<Mention, $this>
*/
public function mentions(): MorphMany
{
return $this->morphMany(Mention::class, 'model');
}
Expand All @@ -60,7 +94,13 @@ public function getActivitylogOptions(): LogOptions
->logOnlyDirty();
}

public function scopePublic($query)
/**
* Scope by public comments.
*
* @param Builder<Comment> $query
* @return Builder<Comment>
*/
public function scopePublic(Builder $query): Builder
{
return $query->where('private', false);
}
Expand Down
78 changes: 64 additions & 14 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

use Filament\Panel;
use App\Enums\UserRole;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use App\Settings\GeneralSettings;
use Laravel\Sanctum\HasApiTokens;
use Filament\Models\Contracts\HasAvatar;
use Illuminate\Notifications\Notifiable;
use Database\Factories\UserSocialFactory;
use Filament\Models\Contracts\FilamentUser;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Relations\HasMany;
Expand All @@ -19,6 +23,7 @@

class User extends Authenticatable implements FilamentUser, HasAvatar, MustVerifyEmail
{
/** @use HasFactory<UserSocialFactory> */
use HasApiTokens, HasFactory, Notifiable;

protected $fillable = [
Expand Down Expand Up @@ -65,12 +70,14 @@ public function hasRole(UserRole ...$roles): bool
return in_array($this->role, $roles);
}

public function getGravatar($size = 150): string
public function getGravatar(int $size = 150): string
{
$email = is_string(Arr::get($this->attributes, 'email')) ? trim(Arr::get($this->attributes, 'email')) : '';

return sprintf(
'%s/%s?s=%d',
config('services.gravatar.base_url'),
md5(strtolower(trim(Arr::get($this->attributes, 'email')))),
config()->string('services.gravatar.base_url'),
md5(strtolower(trim($email))),
(int)$size
);
}
Expand All @@ -80,37 +87,70 @@ public function getFilamentAvatarUrl(): ?string
return $this->getGravatar();
}

public function items()
/**
* Get the user's items.
*
* @return HasMany<Item, $this>
*/
public function items(): HasMany
{
return $this->hasMany(Item::class);
}

/**
* Get the projects that user belongs.
*
* @return BelongsToMany<Project, $this>
*/
public function projects(): BelongsToMany
{
return $this->belongsToMany(Project::class, 'project_member')->using(ProjectMember::class);
}

/**
* Get the user's votes.
*
* @return HasMany<Vote, $this>
*/
public function votes(): HasMany
{
return $this->hasMany(Vote::class);
}

public function votedItems()
/**
* Get the user's voted items.
*
* @return HasManyThrough<Item, Vote, $this>
*/
public function votedItems(): HasManyThrough
{
return $this->hasManyThrough(Item::class, Vote::class, 'user_id', 'items.id', 'id', 'model_id');
}

public function comments()
/**
* Get the user's comments.
*
* @return HasMany<Comment, $this>
*/
public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}

public function assignedItems()
/**
* Get the items assigned to the user.
*
* @return BelongsToMany<Item, $this>
*/
public function assignedItems(): BelongsToMany
{
return $this->belongsToMany(Item::class, 'item_user');
}

public function commentedItems()
/**
* @return HasManyThrough<Item, Comment, $this>
*/
public function commentedItems(): hasManyThrough
{
return $this->hasManyThrough(
Item::class,
Expand All @@ -122,35 +162,45 @@ public function commentedItems()
)->withMax('comments', 'created_at')->distinct('comments.item_id');
}

public function mentions()
/**
* Get the user's mentions.
*
* @return MorphToMany<Comment, $this>
*/
public function mentions(): MorphToMany
{
return $this
->morphedByMany(Comment::class, 'model', 'mentions', 'recipient_id')
->where('recipient_type', User::class);
}

public function userSocials()
/**
* Get the user's socials.
*
* @return HasMany<UserSocial, $this>
*/
public function userSocials(): hasMany
{
return $this->hasMany(UserSocial::class);
}

public function wantsNotification($type)
public function wantsNotification(string $type): bool
{
return in_array($type, $this->notification_settings ?? []);
}

public function needsToVerifyEmail() : bool
{
return app(GeneralSettings::class)->users_must_verify_email &&
!auth()->user()->hasVerifiedEmail();
!auth()->user()?->hasVerifiedEmail();
}

public function isSubscribedToItem(Item $item): bool
{
return $item->subscribedVotes()->where('user_id', $this->id)->exists();
}

public function toggleVoteSubscription(int $id, string $type)
public function toggleVoteSubscription(int $id, string $type): void
{
$vote = Vote::where('model_id', $id)
->where('model_type', $type)
Expand All @@ -176,7 +226,7 @@ public static function booted()
});

static::updating(function (self $user) {
$user->username = Str::lower($user->username);
$user->username = Str::lower((string) $user->username);
});
}
}
8 changes: 7 additions & 1 deletion app/Models/UserSocial.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Database\Factories\UserSocialFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class UserSocial extends Model
{
/** @use HasFactory<UserSocialFactory> */
use HasFactory;

public $casts = [
Expand All @@ -19,7 +22,10 @@ class UserSocial extends Model
'updated_at'
];

public function user()
/**
* @return BelongsTo<User, $this>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
Expand Down
19 changes: 19 additions & 0 deletions app/Models/Vote.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Models;

use Database\Factories\VoteFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\MorphTo;
Expand All @@ -10,27 +11,45 @@

class Vote extends Model
{
/** @use HasFactory<VoteFactory> */
use HasFactory;

public $fillable = [
'subscribed'
];

/**
* Get the user that owns the vote.
*
* @return BelongsTo<User, $this>
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}

/**
* @return MorphTo<Model, $this>
*/
public function item(): MorphTo
{
return $this->morphTo('model');
}

/**
* @return MorphTo<Model, $this>
*/
public function model(): MorphTo
{
return $this->morphTo('model');
}

/**
* Scope by subscribed votes.
*
* @param Builder<Vote> $query
* @return Builder<Vote>
*/
public function scopeSubscribed(Builder $query): Builder
{
return $query->where('subscribed', true);
Expand Down
4 changes: 2 additions & 2 deletions app/Traits/HasUpvote.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ trait HasUpvote
{
/**
* Get the votes for parent model.
*
*
* @return MorphMany<Vote, $this>
*/
public function votes(): MorphMany
Expand Down Expand Up @@ -84,7 +84,7 @@ public function getRecentVoterDetails(int $count = 5): Collection|\Illuminate\Su
->map(function ($vote) {
return [
'name' => $vote->user?->name,
'avatar' => $vote->user?->getGravatar('50'),
'avatar' => $vote->user?->getGravatar(50),
];
});
}
Expand Down

0 comments on commit 48c4fff

Please sign in to comment.