feat: admin app version mgmt + notification system
- New tables: app_config, notifications - Admin views: App Version editor, Notification sender - API: GET /api/notifications, POST /api/notifications/:id/read, POST /api/notifications/read-all - App version now stored in DB, editable by super admin - Notifications: send to all users or specific user - Android notification models + API client - Sidebar: App Version + Notifications links for super_admin
This commit is contained in:
99
src/Models/Notification.php
Normal file
99
src/Models/Notification.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace ServerManager\Models;
|
||||
|
||||
use ServerManager\Core\Database;
|
||||
|
||||
class Notification
|
||||
{
|
||||
private Database $db;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->db = Database::getInstance();
|
||||
}
|
||||
|
||||
public function create(array $data): int
|
||||
{
|
||||
$data['created_at'] = date('Y-m-d H:i:s');
|
||||
return $this->db->insert('notifications', $data);
|
||||
}
|
||||
|
||||
public function findById(int $id): ?array
|
||||
{
|
||||
return $this->db->fetch('SELECT * FROM notifications WHERE id = ?', [$id]);
|
||||
}
|
||||
|
||||
public function getForUser(int $userId, int $page = 1, int $perPage = 20): array
|
||||
{
|
||||
$offset = ($page - 1) * $perPage;
|
||||
$total = $this->db->fetch(
|
||||
"SELECT COUNT(*) as total FROM notifications WHERE user_id IS NULL OR user_id = ?",
|
||||
[$userId]
|
||||
);
|
||||
$items = $this->db->fetchAll(
|
||||
"SELECT * FROM notifications WHERE user_id IS NULL OR user_id = ?
|
||||
ORDER BY created_at DESC LIMIT ? OFFSET ?",
|
||||
[$userId, $perPage, $offset]
|
||||
);
|
||||
return [
|
||||
'data' => $items,
|
||||
'total' => (int) ($total['total'] ?? 0),
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total_pages' => (int) ceil((int) ($total['total'] ?? 0) / $perPage),
|
||||
];
|
||||
}
|
||||
|
||||
public function getUnreadCount(int $userId): int
|
||||
{
|
||||
$result = $this->db->fetch(
|
||||
"SELECT COUNT(*) as total FROM notifications
|
||||
WHERE (user_id IS NULL OR user_id = ?) AND is_read = 0",
|
||||
[$userId]
|
||||
);
|
||||
return (int) ($result['total'] ?? 0);
|
||||
}
|
||||
|
||||
public function markAsRead(int $id, int $userId): void
|
||||
{
|
||||
$this->db->update(
|
||||
'notifications',
|
||||
['is_read' => 1, 'read_at' => date('Y-m-d H:i:s')],
|
||||
'id = ? AND (user_id IS NULL OR user_id = ?)',
|
||||
[$id, $userId]
|
||||
);
|
||||
}
|
||||
|
||||
public function markAllAsRead(int $userId): void
|
||||
{
|
||||
$this->db->update(
|
||||
'notifications',
|
||||
['is_read' => 1, 'read_at' => date('Y-m-d H:i:s')],
|
||||
'(user_id IS NULL OR user_id = ?) AND is_read = 0',
|
||||
[$userId]
|
||||
);
|
||||
}
|
||||
|
||||
public function getAll(int $page = 1, int $perPage = 20): array
|
||||
{
|
||||
$offset = ($page - 1) * $perPage;
|
||||
$total = $this->db->fetch("SELECT COUNT(*) as total FROM notifications");
|
||||
$items = $this->db->fetchAll(
|
||||
"SELECT n.*, u.username as target_username
|
||||
FROM notifications n
|
||||
LEFT JOIN users u ON n.user_id = u.id
|
||||
ORDER BY n.created_at DESC LIMIT ? OFFSET ?",
|
||||
[$perPage, $offset]
|
||||
);
|
||||
return [
|
||||
'data' => $items,
|
||||
'total' => (int) ($total['total'] ?? 0),
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
'total_pages' => (int) ceil((int) ($total['total'] ?? 0) / $perPage),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user