Files
biiproject-kit-v1/app/Repositories/NotificationRepository.php
T

139 lines
4.7 KiB
PHP

<?php
namespace App\Repositories;
use App\Models\Notification;
class NotificationRepository extends BaseRepository
{
public function __construct(Notification $model)
{
parent::__construct($model);
}
/**
* Get the list of recipient categories a user is authorized to see.
* Hierarchy: Developer > Administrator > User > all
*/
public function getAuthorizedRecipients($user)
{
$recipients = ['all'];
if ($user->hasRole('Developer')) {
return ['Developer', 'Administrator', 'User', 'all'];
}
if ($user->hasRole('Administrator')) {
return ['Administrator', 'User', 'all'];
}
// Default: only see notifications for 'User' and 'all'
return ['User', 'all'];
}
/**
* Get ALL notifications for a user based on their roles,
* BUT exclude those they have personally deleted/hidden.
*/
public function getActiveNotificationsForUser($user, $offset = 0, $limit = 10)
{
$query = $this->model->query();
// 1. Filter by roles (Broadcast targeting) hierarchical
$authorizedRecipients = $this->getAuthorizedRecipients($user);
$query->whereIn('recipient', $authorizedRecipients);
// 2. Left Join personal interactions
$query->leftJoin('system_notification_user', function ($join) use ($user) {
$join->on('system_notifications.id', '=', 'system_notification_user.notification_id')
->where('system_notification_user.user_id', '=', $user->id);
});
// 3. Exclude personally deleted ones
$query->whereNull('system_notification_user.deleted_at');
// 4. Select needed columns (avoiding ID collision with Join)
return $query->select('system_notifications.*', 'system_notification_user.read_at as personal_read_at')
->latest('system_notifications.created_at')
->skip($offset)
->take($limit)
->get();
}
/**
* Get personal unread count.
*/
public function getUnreadCount($user)
{
$query = $this->model->query();
// Target filtering hierarchical
$authorizedRecipients = $this->getAuthorizedRecipients($user);
$query->whereIn('recipient', $authorizedRecipients);
// Join to check read/deleted status
$query->leftJoin('system_notification_user', function ($join) use ($user) {
$join->on('system_notifications.id', '=', 'system_notification_user.notification_id')
->where('system_notification_user.user_id', '=', $user->id);
});
// Unread = (Global read_at is null AND Personal read_at is null) AND not deleted
$query->whereNull('system_notification_user.read_at')
->whereNull('system_notification_user.deleted_at');
return $query->count();
}
/**
* Personal Mark As Read
*/
public function markAsRead($notificationId, $userId)
{
\DB::table('system_notification_user')->updateOrInsert(
['notification_id' => $notificationId, 'user_id' => $userId],
['read_at' => now(), 'updated_at' => now()]
);
}
/**
* Personal Delete (Hide)
*/
public function personalDelete($notificationId, $userId)
{
\DB::table('system_notification_user')->updateOrInsert(
['notification_id' => $notificationId, 'user_id' => $userId],
['deleted_at' => now(), 'updated_at' => now()]
);
}
/**
* Mark ALL visible notifications as read for this user.
*/
public function markAllAsReadForUser($user)
{
$authorizedRecipients = $this->getAuthorizedRecipients($user);
// 1. Get IDs of notifications that are visible to user but either:
// - Have no entry in pivot (meaning unread)
// - Have an entry with read_at IS NULL and deleted_at IS NULL
$unreadIds = $this->model->query()
->whereIn('recipient', $authorizedRecipients)
->leftJoin('system_notification_user', function ($join) use ($user) {
$join->on('system_notifications.id', '=', 'system_notification_user.notification_id')
->where('system_notification_user.user_id', '=', $user->id);
})
->whereNull('system_notification_user.read_at')
->whereNull('system_notification_user.deleted_at')
->pluck('system_notifications.id');
if ($unreadIds->isEmpty()) {
return;
}
// 2. Perform batch updateOrInsert for each (or just loop if small, but let's stick to markAsRead helper)
foreach ($unreadIds as $id) {
$this->markAsRead($id, $user->id);
}
}
}