This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||
2 | |||
3 | namespace XoopsModules\Newbb; |
||
4 | |||
5 | /** |
||
6 | * NewBB 5.0x, the forum module for XOOPS project |
||
7 | * |
||
8 | * @copyright XOOPS Project (https://xoops.org) |
||
9 | * @license GNU GPL 2 or later (https://www.gnu.org/licenses/gpl-2.0.html) |
||
10 | * @author Taiwen Jiang (phppp or D.J.) <[email protected]> |
||
11 | * @since 4.00 |
||
12 | * @package module::newbb |
||
13 | */ |
||
14 | |||
15 | |||
16 | |||
17 | \defined('NEWBB_FUNCTIONS_INI') || require __DIR__ . '/functions.ini.php'; |
||
18 | |||
19 | \define('NEWBB_STATS_TYPE_TOPIC', 1); |
||
20 | \define('NEWBB_STATS_TYPE_POST', 2); |
||
21 | \define('NEWBB_STATS_TYPE_DIGEST', 3); |
||
22 | \define('NEWBB_STATS_TYPE_VIEW', 4); |
||
23 | |||
24 | \define('NEWBB_STATS_PERIOD_TOTAL', 1); |
||
25 | \define('NEWBB_STATS_PERIOD_DAY', 2); |
||
26 | \define('NEWBB_STATS_PERIOD_WEEK', 3); |
||
27 | \define('NEWBB_STATS_PERIOD_MONTH', 4); |
||
28 | |||
29 | /** |
||
30 | * Stats for forum |
||
31 | */ |
||
32 | class StatsHandler |
||
33 | { |
||
34 | public $db; |
||
35 | public $table; |
||
36 | public $param = [ |
||
37 | 'type' => ['topic', 'post', 'digest', 'view'], |
||
38 | 'period' => ['total', 'day', 'week', 'month'], |
||
39 | ]; |
||
40 | |||
41 | /** |
||
42 | * @param null|\XoopsDatabase $db |
||
43 | */ |
||
44 | public function __construct(\XoopsDatabase $db = null) |
||
0 ignored issues
–
show
|
|||
45 | { |
||
46 | //$this->db = $db; |
||
47 | //if (!$db || !($db instanceof \XoopsDatabase)) { |
||
48 | $this->db = $GLOBALS['xoopsDB']; |
||
49 | //} |
||
50 | $this->table = $this->db->prefix('newbb_stats'); |
||
51 | } |
||
52 | |||
53 | /** |
||
54 | * @param null|\XoopsDatabase $db |
||
55 | * @return StatsHandler |
||
56 | */ |
||
57 | public static function getInstance(\XoopsDatabase $db = null) |
||
58 | { |
||
59 | static $instance; |
||
60 | if (null === $instance) { |
||
61 | $instance = new static($db); |
||
62 | } |
||
63 | |||
64 | return $instance; |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * @param $id |
||
69 | * @param $type |
||
70 | * @param int $increment |
||
71 | * @return bool |
||
72 | */ |
||
73 | public function update($id, $type, $increment = 1) |
||
74 | { |
||
75 | $id = (int)$id; |
||
76 | $increment = (int)$increment; |
||
77 | |||
78 | if (empty($increment) || false === ($type = \array_search($type, $this->param['type'], true))) { |
||
79 | return false; |
||
80 | } |
||
81 | |||
82 | $sql = " UPDATE {$this->table}" |
||
83 | . ' SET stats_value = CASE ' |
||
84 | . " WHEN time_format = '' OR DATE_FORMAT(time_update, time_format) = DATE_FORMAT(NOW(), time_format) THEN stats_value + '{$increment}' " |
||
85 | . " ELSE '{$increment}' " |
||
86 | . ' END, ' |
||
87 | . ' time_update = NOW()' |
||
88 | . ' WHERE ' |
||
89 | . " (stats_id = '0' OR stats_id = '{$id}') " |
||
90 | . " AND stats_type='{$type}' "; |
||
91 | $result = $this->db->queryF($sql); |
||
0 ignored issues
–
show
|
|||
92 | $rows = $this->db->getAffectedRows(); |
||
93 | if (0 == $rows) { |
||
94 | $sql = " INSERT INTO {$this->table}" |
||
95 | . ' (`stats_id`, `stats_value`, `stats_type`, `stats_period`, `time_update`, `time_format`) ' |
||
96 | . ' VALUES ' |
||
97 | . " ('0', '{$increment}', '{$type}', '" |
||
98 | . \array_search('total', $this->param['period'], true) |
||
99 | . "', NOW(), ''), " |
||
100 | . " ('0', '{$increment}', '{$type}', '" |
||
101 | . \array_search('day', $this->param['period'], true) |
||
102 | . "', NOW(), '%Y%j'), " |
||
103 | . " ('0', '{$increment}', '{$type}', '" |
||
104 | . \array_search('week', $this->param['period'], true) |
||
105 | . "', NOW(), '%Y%u'), " |
||
106 | . " ('0', '{$increment}', '{$type}', '" |
||
107 | . \array_search('month', $this->param['period'], true) |
||
108 | . "', NOW(), '%Y%m')"; |
||
109 | $result = $this->db->queryF($sql); |
||
110 | } |
||
111 | if ($rows < 2 * \count($this->param['period']) && !empty($id)) { |
||
112 | $sql = " INSERT INTO {$this->table}" |
||
113 | . ' (`stats_id`, `stats_value`, `stats_type`, `stats_period`, `time_update`, `time_format`) ' |
||
114 | . ' VALUES ' |
||
115 | . " ('{$id}', '{$increment}', '{$type}', '" |
||
116 | . \array_search('total', $this->param['period'], true) |
||
117 | . "', NOW(), ''), " |
||
118 | . " ('{$id}', '{$increment}', '{$type}', '" |
||
119 | . \array_search('day', $this->param['period'], true) |
||
120 | . "', NOW(), '%Y%j'), " |
||
121 | . " ('{$id}', '{$increment}', '{$type}', '" |
||
122 | . \array_search('week', $this->param['period'], true) |
||
123 | . "', NOW(), '%Y%u'), " |
||
124 | . " ('{$id}', '{$increment}', '{$type}', '" |
||
125 | . \array_search('month', $this->param['period'], true) |
||
126 | . "', NOW(), '%Y%m')"; |
||
127 | $result = $this->db->queryF($sql); |
||
128 | } |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Get stats of "Today" |
||
133 | * |
||
134 | * @param array $ids ID of forum: > 0, forum; 0 - global; empty - all |
||
135 | * @param array $types type of stats items: 1 - topic; 2 - post; 3 - digest; 4 - click; empty - all |
||
136 | * @param array $periods time period: 1 - all time; 2 - today; 3 - this week; 4 - this month; empty - all |
||
137 | * @return array |
||
138 | */ |
||
139 | public function getStats(array $ids, array $types = [], array $periods = []) |
||
140 | { |
||
141 | $ret = []; |
||
142 | |||
143 | $_types = []; |
||
144 | foreach ($types as $type) { |
||
145 | $_types[] = \array_search($type, $this->param['type'], true); |
||
146 | } |
||
147 | $_periods = []; |
||
148 | foreach ($periods as $period) { |
||
149 | $_periods[] = \array_search($period, $this->param['period'], true); |
||
150 | } |
||
151 | $sql = ' SELECT stats_id, stats_value, stats_type, stats_period ' . " FROM {$this->table} " . ' WHERE ' . " ( time_format = '' OR DATE_FORMAT(time_update, time_format) = DATE_FORMAT(NOW(), time_format) ) " . ' ' . (empty($ids) ? '' : 'AND stats_id IN (' . \implode( |
||
152 | ', ', |
||
153 | \array_map( |
||
154 | '\intval', |
||
155 | $ids |
||
156 | ) |
||
157 | ) . ')') . ' ' . (empty($_types) ? '' : 'AND stats_type IN (' . \implode(', ', $_types) . ')') . ' ' . (empty($_periods) ? '' : 'AND stats_period IN (' . \implode(', ', $_periods) . ')'); |
||
158 | $result = $this->db->query($sql); |
||
159 | |||
160 | while (false !== ($row = $this->db->fetchArray($result))) { |
||
161 | $ret[(string)$row['stats_id']][$this->param['type'][$row['stats_type']]][$this->param['period'][$row['stats_period']]] = $row['stats_value']; |
||
162 | } |
||
163 | |||
164 | return $ret; |
||
165 | } |
||
166 | |||
167 | public function reset() |
||
168 | { |
||
169 | $this->db->queryF('TRUNCATE TABLE ' . $this->table); |
||
170 | $now = \time(); |
||
171 | $time_start = [ |
||
172 | 'day' => '%Y%j', |
||
173 | 'week' => '%Y%u', |
||
174 | 'month' => '%Y%m', |
||
175 | ]; |
||
176 | $counts = []; |
||
177 | |||
178 | $sql = ' SELECT forum_id' . ' FROM ' . $this->db->prefix('newbb_forums'); |
||
179 | $ret = $this->db->query($sql); |
||
180 | while (list($forum_id) = $this->db->fetchRow($ret)) { |
||
181 | $sql = ' SELECT COUNT(*), SUM(topic_views)' . ' FROM ' . $this->db->prefix('newbb_topics') . " WHERE approved=1 AND forum_id = {$forum_id}"; |
||
182 | $result = $this->db->query($sql); |
||
183 | [$topics, $views] = $this->db->fetchRow($result); |
||
184 | $this->update($forum_id, 'topic', $topics); |
||
185 | $this->update($forum_id, 'view', $views); |
||
186 | |||
187 | $sql = ' SELECT COUNT(*)' . ' FROM ' . $this->db->prefix('newbb_topics') . " WHERE approved=1 AND topic_digest >0 AND forum_id = {$forum_id}"; |
||
188 | $result = $this->db->query($sql); |
||
189 | [$digests] = $this->db->fetchRow($result); |
||
190 | $this->update($forum_id, 'digest', $digests); |
||
191 | |||
192 | $sql = ' SELECT COUNT(*)' . ' FROM ' . $this->db->prefix('newbb_posts') . " WHERE approved=1 AND forum_id = {$forum_id}"; |
||
193 | $result = $this->db->query($sql); |
||
194 | [$posts] = $this->db->fetchRow($result); |
||
195 | $this->update($forum_id, 'post', $posts); |
||
196 | |||
197 | foreach ($time_start as $period => $format) { |
||
198 | $sql = ' SELECT COUNT(*), SUM(topic_views)' . ' FROM ' . $this->db->prefix('newbb_topics') . " WHERE approved=1 AND forum_id = {$forum_id}" . " AND FROM_UNIXTIME(topic_time, '{$format}') >= FROM_UNIXTIME({$now}, '{$format}')"; |
||
199 | $result = $this->db->query($sql); |
||
200 | [$topics, $views] = $this->db->fetchRow($result); |
||
201 | $views = empty($views) ? 0 : $views; // null check |
||
202 | $this->db->queryF( |
||
203 | " INSERT INTO {$this->table}" . ' (`stats_id`, `stats_value`, `stats_type`, `stats_period`, `time_update`, `time_format`) ' . ' VALUES ' . " ('{$forum_id}', '{$topics}', '" . \array_search('topic', $this->param['type'], true) . "', '" . \array_search( |
||
204 | $period, |
||
205 | $this->param['period'], |
||
206 | true |
||
207 | ) . "', NOW(), '{$format}')" |
||
208 | ); |
||
209 | $this->db->queryF( |
||
210 | " INSERT INTO {$this->table}" . ' (`stats_id`, `stats_value`, `stats_type`, `stats_period`, `time_update`, `time_format`) ' . ' VALUES ' . " ('{$forum_id}', '{$views}', '" . \array_search('view', $this->param['type'], true) . "', '" . \array_search( |
||
211 | $period, |
||
212 | $this->param['period'], |
||
213 | true |
||
214 | ) . "', NOW(), '{$format}')" |
||
215 | ); |
||
216 | @$counts['topic'][$period] += $topics; |
||
217 | @$counts['view'][$period] += $views; |
||
218 | |||
219 | $sql = ' SELECT COUNT(*)' . ' FROM ' . $this->db->prefix('newbb_topics') . " WHERE approved=1 AND topic_digest >0 AND forum_id = {$forum_id}" . " AND FROM_UNIXTIME(digest_time, '{$format}') >= FROM_UNIXTIME({$now}, '{$format}')"; |
||
220 | $result = $this->db->query($sql); |
||
221 | [$digests] = $this->db->fetchRow($result); |
||
222 | $this->db->queryF( |
||
223 | " INSERT INTO {$this->table}" . ' (`stats_id`, `stats_value`, `stats_type`, `stats_period`, `time_update`, `time_format`) ' . ' VALUES ' . " ('{$forum_id}', '{$digests}', '" . \array_search('digest', $this->param['type'], true) . "', '" . \array_search( |
||
224 | $period, |
||
225 | $this->param['period'], |
||
226 | true |
||
227 | ) . "', NOW(), '{$format}')" |
||
228 | ); |
||
229 | @$counts['digest'][$period] += $digests; |
||
230 | |||
231 | $sql = ' SELECT COUNT(*)' . ' FROM ' . $this->db->prefix('newbb_posts') . " WHERE approved=1 AND forum_id = {$forum_id}" . " AND FROM_UNIXTIME(post_time, '{$format}') >= FROM_UNIXTIME({$now}, '{$format}')"; |
||
232 | $result = $this->db->query($sql); |
||
233 | [$posts] = $this->db->fetchRow($result); |
||
234 | $this->db->queryF( |
||
235 | " INSERT INTO {$this->table}" . ' (`stats_id`, `stats_value`, `stats_type`, `stats_period`, `time_update`, `time_format`) ' . ' VALUES ' . " ('{$forum_id}', '{$posts}', '" . \array_search('post', $this->param['type'], true) . "', '" . \array_search( |
||
236 | $period, |
||
237 | $this->param['period'], |
||
238 | true |
||
239 | ) . "', NOW(), '{$format}')" |
||
240 | ); |
||
241 | @$counts['post'][$period] += $posts; |
||
242 | } |
||
243 | } |
||
244 | |||
245 | $this->db->queryF(" DELETE FROM {$this->table}" . " WHERE stats_id = '0' AND stats_period <> " . \array_search('total', $this->param['period'], true)); |
||
246 | foreach ($time_start as $period => $format) { |
||
247 | foreach (\array_keys($counts) as $type) { |
||
248 | $this->db->queryF( |
||
249 | " INSERT INTO {$this->table}" . ' (`stats_id`, `stats_value`, `stats_type`, `stats_period`, `time_update`, `time_format`) ' . ' VALUES ' . " ('0', '{$counts[$type][$period]}', '" . \array_search($type, $this->param['type'], true) . "', '" . \array_search( |
||
250 | $period, |
||
251 | $this->param['period'], |
||
252 | true |
||
253 | ) . "', NOW(), '{$format}')" |
||
254 | ); |
||
255 | } |
||
256 | } |
||
257 | } |
||
258 | } |
||
259 |
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.