Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
69.06% |
96 / 139 |
|
53.85% |
7 / 13 |
CRAP | |
0.00% |
0 / 1 |
CounterDao | |
69.06% |
96 / 139 |
|
53.85% |
7 / 13 |
27.59 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getAllEditCounts | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
2.00 | |||
getAllEditCountsForKey | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
12 | |||
getEditCountForKeyAndLang | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
deleteAllCountsForKey | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
incrementEditCountForKeyAndLang | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
1 | |||
decrementEditCountForKeyAndLang | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
1 | |||
setEditCountForKeyAndLang | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
1 | |||
getEditStreak | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
2 | |||
setEditStreak | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
1 | |||
incrementRevertCountForKeyAndLang | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
getAllRevertCounts | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
2.00 | |||
getRevertCountForKeyAndLang | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
16 | * |
17 | * @file |
18 | */ |
19 | namespace MediaWiki\Extension\WikimediaEditorTasks; |
20 | |
21 | use Wikimedia\Rdbms\IDatabase; |
22 | use Wikimedia\Rdbms\IDBAccessObject; |
23 | use Wikimedia\Rdbms\IReadableDatabase; |
24 | |
25 | class CounterDao { |
26 | |
27 | /** @var IDatabase */ |
28 | private $dbw; |
29 | |
30 | /** @var IReadableDatabase */ |
31 | private $dbr; |
32 | |
33 | /** |
34 | * CounterDao constructor. |
35 | * @param IDatabase $dbw handle to DB_PRIMARY for writes |
36 | * @param IReadableDatabase $dbr handle to DB_REPLICA for reads |
37 | */ |
38 | public function __construct( $dbw, $dbr ) { |
39 | $this->dbw = $dbw; |
40 | $this->dbr = $dbr; |
41 | } |
42 | |
43 | /** |
44 | * Get all stored counts by lang for the user. |
45 | * @param int $centralId central user ID |
46 | * @return array[] All counts in the form: |
47 | * [ |
48 | * <counter key> => [ |
49 | * <language code> => <count>, |
50 | * ... |
51 | * ], |
52 | * ... |
53 | * ] |
54 | */ |
55 | public function getAllEditCounts( $centralId ) { |
56 | $wrapper = $this->dbr->newSelectQueryBuilder() |
57 | ->select( [ 'wet_key', 'wetc_lang', 'wetc_count' ] ) |
58 | ->from( 'wikimedia_editor_tasks_counts' ) |
59 | ->leftJoin( 'wikimedia_editor_tasks_keys', null, 'wet_id=wetc_key_id' ) |
60 | ->where( [ 'wetc_user' => $centralId ] ) |
61 | ->caller( __METHOD__ ) |
62 | ->fetchResultSet(); |
63 | $result = []; |
64 | foreach ( $wrapper as $row ) { |
65 | $result[$row->wet_key][$row->wetc_lang] = (int)$row->wetc_count; |
66 | } |
67 | return $result; |
68 | } |
69 | |
70 | /** |
71 | * Get all counts by lang for a specific key for a user. |
72 | * @param int $centralId central user ID |
73 | * @param int $keyId counter key ID |
74 | * @param int $flags IDBAccessObject flags |
75 | * @return array counts for all langs for the specified key |
76 | */ |
77 | public function getAllEditCountsForKey( $centralId, $keyId, $flags = 0 ) { |
78 | if ( ( $flags & IDBAccessObject::READ_LATEST ) == IDBAccessObject::READ_LATEST ) { |
79 | $db = $this->dbw; |
80 | } else { |
81 | $db = $this->dbr; |
82 | } |
83 | |
84 | $wrapper = $db->newSelectQueryBuilder() |
85 | ->select( [ 'wetc_lang', 'wetc_count' ] ) |
86 | ->from( 'wikimedia_editor_tasks_counts' ) |
87 | ->where( [ 'wetc_user' => $centralId, 'wetc_key_id' => $keyId ] ) |
88 | ->recency( $flags ) |
89 | ->caller( __METHOD__ )->fetchResultSet(); |
90 | $result = []; |
91 | foreach ( $wrapper as $row ) { |
92 | $result[$row->wetc_lang] = (int)$row->wetc_count; |
93 | } |
94 | return $result; |
95 | } |
96 | |
97 | /** |
98 | * Get a single count by key and lang for a user. |
99 | * @param int $centralId central user ID |
100 | * @param int $keyId counter key ID |
101 | * @param string $lang language code |
102 | * @return int count for the specified key (returns 0 if not found) |
103 | */ |
104 | public function getEditCountForKeyAndLang( $centralId, $keyId, $lang ) { |
105 | return (int)$this->dbr->newSelectQueryBuilder() |
106 | ->select( 'wetc_count' ) |
107 | ->from( 'wikimedia_editor_tasks_counts' ) |
108 | ->where( [ |
109 | 'wetc_user' => $centralId, |
110 | 'wetc_key_id' => $keyId, |
111 | 'wetc_lang' => $lang, |
112 | ] ) |
113 | ->caller( __METHOD__ ) |
114 | ->fetchField(); |
115 | } |
116 | |
117 | /** |
118 | * Delete counts for all languages for a single key and user. |
119 | * @param int $centralId central user ID |
120 | * @param int $keyId ID for counter key |
121 | */ |
122 | public function deleteAllCountsForKey( $centralId, $keyId ) { |
123 | $this->dbw->newDeleteQueryBuilder() |
124 | ->deleteFrom( 'wikimedia_editor_tasks_counts' ) |
125 | ->where( [ |
126 | 'wetc_user' => $centralId, |
127 | 'wetc_key_id' => $keyId, |
128 | ] ) |
129 | ->caller( __METHOD__ ) |
130 | ->execute(); |
131 | } |
132 | |
133 | /** |
134 | * Increment a user's count for a key and language. |
135 | * @param int $centralId central user ID |
136 | * @param int $keyId |
137 | * @param string $lang language code for this count |
138 | */ |
139 | public function incrementEditCountForKeyAndLang( $centralId, $keyId, $lang ) { |
140 | $this->dbw->newUpdateQueryBuilder() |
141 | ->update( 'wikimedia_editor_tasks_counts' ) |
142 | ->set( [ 'wetc_count = wetc_count + 1' ] ) |
143 | ->where( [ |
144 | 'wetc_user' => $centralId, |
145 | 'wetc_key_id' => $keyId, |
146 | 'wetc_lang' => $lang, |
147 | ] ) |
148 | ->caller( __METHOD__ ) |
149 | ->execute(); |
150 | } |
151 | |
152 | /** |
153 | * Decrement a user's count for a key and language. |
154 | * @param int $centralId central user ID |
155 | * @param int $keyId |
156 | * @param string $lang language code for this count |
157 | */ |
158 | public function decrementEditCountForKeyAndLang( $centralId, $keyId, $lang ) { |
159 | $this->dbw->newUpdateQueryBuilder() |
160 | ->update( 'wikimedia_editor_tasks_counts' ) |
161 | ->set( [ 'wetc_count = wetc_count - 1' ] ) |
162 | ->where( [ |
163 | 'wetc_user' => $centralId, |
164 | 'wetc_key_id' => $keyId, |
165 | 'wetc_lang' => $lang, |
166 | $this->dbw->expr( 'wetc_count', '>', 0 ), |
167 | ] ) |
168 | ->caller( __METHOD__ ) |
169 | ->execute(); |
170 | } |
171 | |
172 | /** |
173 | * Set the count for a given counter. |
174 | * @param int $centralId central user ID |
175 | * @param int $keyId counter key ID |
176 | * @param string $lang language code for this count |
177 | * @param int $count new count |
178 | */ |
179 | public function setEditCountForKeyAndLang( $centralId, $keyId, $lang, $count ) { |
180 | $this->dbw->newInsertQueryBuilder() |
181 | ->insertInto( 'wikimedia_editor_tasks_counts' ) |
182 | ->row( [ |
183 | 'wetc_user' => $centralId, |
184 | 'wetc_key_id' => $keyId, |
185 | 'wetc_lang' => $lang, |
186 | 'wetc_count' => $count, |
187 | ] ) |
188 | ->onDuplicateKeyUpdate() |
189 | ->uniqueIndexFields( [ 'wetc_user', 'wetc_key_id', 'wetc_lang' ] ) |
190 | ->set( [ 'wetc_count = wetc_count + ' . (int)$count ] ) |
191 | ->caller( __METHOD__ ) |
192 | ->execute(); |
193 | } |
194 | |
195 | /** |
196 | * Get the edit streak length and last edit time for the user |
197 | * @param int $centralId central user ID |
198 | * @return array[] An array contains current streak length and last edit time |
199 | */ |
200 | public function getEditStreak( $centralId ) { |
201 | $wrapper = $this->dbr->newSelectQueryBuilder() |
202 | ->select( [ 'wetes_streak_length', 'wetes_last_edit_time' ] ) |
203 | ->from( 'wikimedia_editor_tasks_edit_streak' ) |
204 | ->where( [ 'wetes_user' => $centralId ] ) |
205 | ->caller( __METHOD__ ) |
206 | ->fetchRow(); |
207 | $result = []; |
208 | if ( $wrapper != false ) { |
209 | $result['length'] = (int)$wrapper->wetes_streak_length; |
210 | $result['last_edit_time'] = $wrapper->wetes_last_edit_time; |
211 | } |
212 | return $result; |
213 | } |
214 | |
215 | /** |
216 | * Set the edit streak for a user. |
217 | * Increase the edit streak length if the user makes an edit within 2 days. |
218 | * @param int $centralId central user ID |
219 | */ |
220 | public function setEditStreak( $centralId ) { |
221 | $currentTime = $this->dbw->timestamp( time() ); |
222 | $this->dbw->newInsertQueryBuilder() |
223 | ->insertInto( 'wikimedia_editor_tasks_edit_streak' ) |
224 | ->row( [ |
225 | 'wetes_user' => $centralId, |
226 | 'wetes_streak_length' => 1, |
227 | 'wetes_last_edit_time' => $currentTime, |
228 | ] ) |
229 | ->onDuplicateKeyUpdate() |
230 | ->uniqueIndexFields( 'wetes_user' ) |
231 | ->set( [ |
232 | 'wetes_streak_length = IF ( |
233 | DATEDIFF ( ' . $currentTime . ', wetes_last_edit_time ) >= 2, |
234 | 1, |
235 | IF ( |
236 | DATEDIFF ( ' . $currentTime . ', wetes_last_edit_time ) = 1, |
237 | wetes_streak_length + 1, |
238 | wetes_streak_length |
239 | ) |
240 | )', |
241 | 'wetes_last_edit_time' => $currentTime, |
242 | ] ) |
243 | ->caller( __METHOD__ ) |
244 | ->execute(); |
245 | } |
246 | |
247 | /** |
248 | * Increment a user's revert count for a key and language. |
249 | * @param int $centralId central user ID |
250 | * @param int $keyId |
251 | * @param string $lang language code for this count |
252 | */ |
253 | public function incrementRevertCountForKeyAndLang( $centralId, $keyId, $lang ) { |
254 | $this->dbw->newUpdateQueryBuilder() |
255 | ->update( 'wikimedia_editor_tasks_counts' ) |
256 | ->set( [ 'wetc_revert_count = wetc_revert_count + 1' ] ) |
257 | ->where( [ |
258 | 'wetc_user' => $centralId, |
259 | 'wetc_key_id' => $keyId, |
260 | 'wetc_lang' => $lang, |
261 | ] ) |
262 | ->caller( __METHOD__ ) |
263 | ->execute(); |
264 | } |
265 | |
266 | /** |
267 | * Get all stored reverts counts by lang for the user. |
268 | * @param int $centralId central user ID |
269 | * @return array[] All counts in the form: |
270 | * [ |
271 | * <counter key> => [ |
272 | * <language code> => <count>, |
273 | * ... |
274 | * ], |
275 | * ... |
276 | * ] |
277 | */ |
278 | public function getAllRevertCounts( $centralId ) { |
279 | $wrapper = $this->dbr->newSelectQueryBuilder() |
280 | ->select( [ 'wet_key', 'wetc_lang', 'wetc_revert_count' ] ) |
281 | ->from( 'wikimedia_editor_tasks_counts' ) |
282 | ->leftJoin( 'wikimedia_editor_tasks_keys', null, 'wet_id=wetc_key_id' ) |
283 | ->where( [ 'wetc_user' => $centralId ] ) |
284 | ->caller( __METHOD__ ) |
285 | ->fetchResultSet(); |
286 | $result = []; |
287 | foreach ( $wrapper as $row ) { |
288 | $result[$row->wet_key][$row->wetc_lang] = (int)$row->wetc_revert_count; |
289 | } |
290 | return $result; |
291 | } |
292 | |
293 | /** |
294 | * Get a single revert count by key and lang for a user. |
295 | * @param int $centralId central user ID |
296 | * @param int $keyId counter key ID |
297 | * @param string $lang language code |
298 | * @return int revert count for the specified key (returns 0 if not found) |
299 | */ |
300 | public function getRevertCountForKeyAndLang( $centralId, $keyId, $lang ) { |
301 | return (int)$this->dbr->newSelectQueryBuilder() |
302 | ->select( 'wetc_revert_count' ) |
303 | ->from( 'wikimedia_editor_tasks_counts' ) |
304 | ->where( [ |
305 | 'wetc_user' => $centralId, |
306 | 'wetc_key_id' => $keyId, |
307 | 'wetc_lang' => $lang, |
308 | ] ) |
309 | ->caller( __METHOD__ ) |
310 | ->fetchField(); |
311 | } |
312 | } |