Lines 98.63% 72 / 73
Methods 88.88% 8 / 9
Classes 0.00% 0 / 1
Covered by tests of size
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 countOnlineUsersFromSessions 100.00% 11 / 11 100.00% 1 / 1 4
 countOnlineUsersFromFaqUser 90.90% 10 / 11 0.00% 0 / 1 4.01
 getTimeBySessionId 100.00% 7 / 7 100.00% 1 / 1 4
 getSessionsByDateRange 100.00% 14 / 14 100.00% 1 / 1 4
 countTotalSessions 100.00% 6 / 6 100.00% 1 / 1 3
 deleteSessionsByTimeRange 100.00% 7 / 7 100.00% 1 / 1 1
 deleteAllSessions 100.00% 2 / 2 100.00% 1 / 1 1
 getSessionTimestamps 100.00% 14 / 14 100.00% 1 / 1 4
25readonly class SessionRepository
26{
27    public function __construct(
28        private Configuration $configuration,
29    ) {
30    }
31
32    /**
33     * Counts distinct user IDs from sessions within a time window.
34     */
35    public function countOnlineUsersFromSessions(int $minTimestamp): int
36    {
37        $query = sprintf(
38            'SELECT COUNT(DISTINCT user_id) AS cnt FROM %sfaqsessions WHERE time >= %d AND user_id > 0',
39            Database::getTablePrefix(),
40            $minTimestamp,
41        );
42
43        $result = $this->configuration->getDb()->query($query);
44        if ($result) {
45            $row = $this->configuration->getDb()->fetchObject($result);
46            if (is_object($row) && property_exists($row, 'cnt')) {
47                return (int) $row->cnt;
48            }
49        }
50
51        return 0;
52    }
53
54    /**
55     * Counts users with active sessions from the faquser table.
56     */
57    public function countOnlineUsersFromFaqUser(int $minTimestamp): int
58    {
59        $query = sprintf(
60            'SELECT COUNT(*) AS cnt FROM %sfaquser WHERE session_id IS NOT NULL AND session_timestamp >= %d AND success = 1',
61            Database::getTablePrefix(),
62            $minTimestamp,
63        );
64
65        $result = $this->configuration->getDb()->query($query);
66        if ($result) {
67            $row = $this->configuration->getDb()->fetchObject($result);
68            if (is_object($row) && property_exists($row, 'cnt')) {
69                return (int) $row->cnt;
70            }
71        }
72
73        return 0;
74    }
75
76    /**
77     * Fetches the timestamp for a specific session ID.
78     */
79    public function getTimeBySessionId(int $sessionId): int
80    {
81        $query = sprintf('SELECT time FROM %sfaqsessions WHERE sid = %d', Database::getTablePrefix(), $sessionId);
82
83        $result = $this->configuration->getDb()->query($query);
84
85        if ($result) {
86            $res = $this->configuration->getDb()->fetchObject($result);
87            if (is_object($res) && property_exists($res, 'time')) {
88                return (int) $res->time;
89            }
90        }
91
92        return 0;
93    }
94
95    /**
96     * Fetches all sessions within a time range.
97     *
98     * @return array<int, \stdClass>
99     */
100    public function getSessionsByDateRange(int $firstHour, int $lastHour): array
101    {
102        $query = sprintf(
103            'SELECT sid, ip, time FROM %sfaqsessions WHERE time > %d AND time < %d ORDER BY time',
104            Database::getTablePrefix(),
105            $firstHour,
106            $lastHour,
107        );
108
109        $result = $this->configuration->getDb()->query($query);
110        $sessions = [];
111
112        while (true) {
113            $row = $this->configuration->getDb()->fetchObject($result);
114            if ($row === null || $row === false) {
115                break;
116            }
117
118            $sessions[] = $row;
119        }
120
121        return $sessions;
122    }
123
124    /**
125     * Counts the total number of sessions.
126     */
127    public function countTotalSessions(): int
128    {
129        $query = sprintf('SELECT COUNT(sid) as num_sessions FROM %sfaqsessions', Database::getTablePrefix());
130
131        $result = $this->configuration->getDb()->query($query);
132        if ($result) {
133            $row = $this->configuration->getDb()->fetchObject($result);
134            return $row instanceof \stdClass ? (int) $row->num_sessions : 0;
135        }
136
137        return 0;
138    }
139
140    /**
141     * Deletes sessions within a time range.
142     */
143    public function deleteSessionsByTimeRange(int $first, int $last): bool
144    {
145        $query = sprintf(
146            'DELETE FROM %sfaqsessions WHERE time >= %d AND time <= %d',
147            Database::getTablePrefix(),
148            $first,
149            $last,
150        );
151
152        return (bool) $this->configuration->getDb()->query($query);
153    }
154
155    /**
156     * Deletes all sessions.
157     */
158    public function deleteAllSessions(): bool
159    {
160        $query = sprintf('DELETE FROM %sfaqsessions', Database::getTablePrefix());
161
162        return (bool) $this->configuration->getDb()->query($query);
163    }
164
165    /**
166     * Fetches all session timestamps within a time range.
167     *
168     * @return array<int, int>
169     */
170    public function getSessionTimestamps(int $startDate, int $endDate): array
171    {
172        $query = sprintf(
173            'SELECT time FROM %sfaqsessions WHERE time > %d AND time < %d;',
174            Database::getTablePrefix(),
175            $startDate,
176            $endDate,
177        );
178
179        $result = $this->configuration->getDb()->query($query);
180        $timestamps = [];
181
182        while (true) {
183            $row = $this->configuration->getDb()->fetchObject($result);
184            if ($row === null || $row === false) {
185                break;
186            }
187
188            $timestamps[] = (int) $row->time;
189        }
190
191        return $timestamps;
192    }
193}