181 lines
4.5 KiB
PHP
181 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace Paymenter\Extensions\Others\SocialBase\Traits;
|
|
|
|
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
|
use Paymenter\Extensions\Others\SocialBase\Models\Reaction;
|
|
use App\Models\User;
|
|
|
|
trait HasReactions
|
|
{
|
|
/**
|
|
* Get all reactions for this model
|
|
*/
|
|
public function reactions(): MorphMany
|
|
{
|
|
return $this->morphMany(Reaction::class, 'reactable');
|
|
}
|
|
|
|
/**
|
|
* Get reaction counts grouped by type
|
|
*/
|
|
public function getReactionCountsAttribute(): array
|
|
{
|
|
return $this->reactions
|
|
->groupBy('type')
|
|
->map(function ($reactions) {
|
|
return $reactions->count();
|
|
})
|
|
->toArray();
|
|
}
|
|
|
|
/**
|
|
* Get total reaction count
|
|
*/
|
|
public function getTotalReactionsAttribute(): int
|
|
{
|
|
return $this->reactions->count();
|
|
}
|
|
|
|
/**
|
|
* Check if user has reacted to this model
|
|
*/
|
|
public function hasReactionFromUser(?User $user = null, ?string $type = null): bool
|
|
{
|
|
if (!$user) {
|
|
return false;
|
|
}
|
|
|
|
$query = $this->reactions()->where('user_id', $user->id);
|
|
|
|
if ($type) {
|
|
$query->where('type', $type);
|
|
}
|
|
|
|
return $query->exists();
|
|
}
|
|
|
|
/**
|
|
* Get user's reaction to this model
|
|
*/
|
|
public function getUserReaction(?User $user = null): ?Reaction
|
|
{
|
|
if (!$user) {
|
|
return null;
|
|
}
|
|
|
|
return $this->reactions()->where('user_id', $user->id)->first();
|
|
}
|
|
|
|
/**
|
|
* Add or update a reaction from a user
|
|
*/
|
|
public function addReaction(User $user, string $type): Reaction
|
|
{
|
|
return $this->reactions()->updateOrCreate(
|
|
['user_id' => $user->id],
|
|
['type' => $type]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Remove a reaction from a user
|
|
*/
|
|
public function removeReaction(User $user, ?string $type = null): bool
|
|
{
|
|
$query = $this->reactions()->where('user_id', $user->id);
|
|
|
|
if ($type) {
|
|
$query->where('type', $type);
|
|
}
|
|
|
|
return $query->delete() > 0;
|
|
}
|
|
|
|
/**
|
|
* Toggle a reaction from a user
|
|
* Returns: 'added', 'updated', or 'removed'
|
|
*/
|
|
public function toggleReaction(User $user, string $type): string
|
|
{
|
|
$existingReaction = $this->getUserReaction($user);
|
|
|
|
if ($existingReaction) {
|
|
if ($existingReaction->type === $type) {
|
|
// Same reaction - remove it
|
|
$existingReaction->delete();
|
|
return 'removed';
|
|
} else {
|
|
// Different reaction - update it
|
|
$existingReaction->update(['type' => $type]);
|
|
return 'updated';
|
|
}
|
|
} else {
|
|
// No existing reaction - create new one
|
|
$this->addReaction($user, $type);
|
|
return 'added';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get reactions grouped by type with user information
|
|
*/
|
|
public function getReactionsWithUsersAttribute(): array
|
|
{
|
|
return $this->reactions()
|
|
->with('user:id,name')
|
|
->get()
|
|
->groupBy('type')
|
|
->map(function ($reactions) {
|
|
return $reactions->map(function ($reaction) {
|
|
return [
|
|
'user_id' => $reaction->user->id,
|
|
'user_name' => $reaction->user->name,
|
|
'created_at' => $reaction->created_at->diffForHumans(),
|
|
];
|
|
});
|
|
})
|
|
->toArray();
|
|
}
|
|
|
|
/**
|
|
* Get the most popular reaction type
|
|
*/
|
|
public function getMostPopularReactionAttribute(): ?string
|
|
{
|
|
$counts = $this->reaction_counts;
|
|
|
|
if (empty($counts)) {
|
|
return null;
|
|
}
|
|
|
|
return array_keys($counts, max($counts))[0];
|
|
}
|
|
|
|
/**
|
|
* Scope to order by reaction count
|
|
*/
|
|
public function scopeOrderByReactions($query, string $direction = 'desc')
|
|
{
|
|
return $query->withCount('reactions')
|
|
->orderBy('reactions_count', $direction);
|
|
}
|
|
|
|
/**
|
|
* Scope to filter models with reactions
|
|
*/
|
|
public function scopeWithReactions($query)
|
|
{
|
|
return $query->has('reactions');
|
|
}
|
|
|
|
/**
|
|
* Scope to filter models by specific reaction type
|
|
*/
|
|
public function scopeWithReactionType($query, string $type)
|
|
{
|
|
return $query->whereHas('reactions', function ($q) use ($type) {
|
|
$q->where('type', $type);
|
|
});
|
|
}
|
|
} |