feat: add app and database modules
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user