Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
71.14% covered (warning)
71.14%
106 / 149
53.85% covered (warning)
53.85%
7 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
CounterDao
71.14% covered (warning)
71.14%
106 / 149
53.85% covered (warning)
53.85%
7 / 13
25.79
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getAllEditCounts
94.12% covered (success)
94.12%
16 / 17
0.00% covered (danger)
0.00%
0 / 1
2.00
 getAllEditCountsForKey
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 getEditCountForKeyAndLang
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 deleteAllCountsForKey
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
 incrementEditCountForKeyAndLang
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 decrementEditCountForKeyAndLang
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 setEditCountForKeyAndLang
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
1
 getEditStreak
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 setEditStreak
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
1
 incrementRevertCountForKeyAndLang
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 getAllRevertCounts
94.12% covered (success)
94.12%
16 / 17
0.00% covered (danger)
0.00%
0 / 1
2.00
 getRevertCountForKeyAndLang
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
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 */
19namespace MediaWiki\Extension\WikimediaEditorTasks;
20
21use IDBAccessObject;
22use Wikimedia\Rdbms\DBConnRef;
23
24class CounterDao {
25
26    /** @var DBConnRef */
27    private $dbw;
28
29    /** @var DBConnRef */
30    private $dbr;
31
32    /**
33     * CounterDao constructor.
34     * @param DBConnRef $dbw handle to DB_PRIMARY for writes
35     * @param DBConnRef $dbr handle to DB_REPLICA for reads
36     */
37    public function __construct( $dbw, $dbr ) {
38        $this->dbw = $dbw;
39        $this->dbr = $dbr;
40    }
41
42    /**
43     * Get all stored counts by lang for the user.
44     * @param int $centralId central user ID
45     * @return array[] All counts in the form:
46     * [
47     *     <counter key> => [
48     *         <language code> => <count>,
49     *         ...
50     *     ],
51     *     ...
52     * ]
53     */
54    public function getAllEditCounts( $centralId ) {
55        $wrapper = $this->dbr->select(
56            [ 'wikimedia_editor_tasks_counts', 'wikimedia_editor_tasks_keys' ],
57            [ 'wet_key', 'wetc_lang', 'wetc_count' ],
58            [ 'wetc_user' => $centralId ],
59            __METHOD__,
60            [],
61            [
62                'wikimedia_editor_tasks_keys' => [
63                    'LEFT JOIN',
64                    'wet_id=wetc_key_id',
65                ],
66            ]
67        );
68        $result = [];
69        foreach ( $wrapper as $row ) {
70            $result[$row->wet_key][$row->wetc_lang] = (int)$row->wetc_count;
71        }
72        return $result;
73    }
74
75    /**
76     * Get all counts by lang for a specific key for a user.
77     * @param int $centralId central user ID
78     * @param int $keyId counter key ID
79     * @param int $flags IDBAccessObject flags
80     * @return array counts for all langs for the specified key
81     */
82    public function getAllEditCountsForKey( $centralId, $keyId, $flags = 0 ) {
83        if ( ( $flags & IDBAccessObject::READ_LATEST ) == IDBAccessObject::READ_LATEST ) {
84            $db = $this->dbw;
85        } else {
86            $db = $this->dbr;
87        }
88
89        $wrapper = $db->newSelectQueryBuilder()
90            ->select( [ 'wetc_lang', 'wetc_count' ] )
91            ->from( 'wikimedia_editor_tasks_counts' )
92            ->where( [ 'wetc_user' => $centralId, 'wetc_key_id' => $keyId ] )
93            ->recency( $flags )
94            ->caller( __METHOD__ )->fetchResultSet();
95        $result = [];
96        foreach ( $wrapper as $row ) {
97            $result[$row->wetc_lang] = (int)$row->wetc_count;
98        }
99        return $result;
100    }
101
102    /**
103     * Get a single count by key and lang for a user.
104     * @param int $centralId central user ID
105     * @param int $keyId counter key ID
106     * @param string $lang language code
107     * @return int count for the specified key (returns 0 if not found)
108     */
109    public function getEditCountForKeyAndLang( $centralId, $keyId, $lang ) {
110        return (int)$this->dbr->selectField(
111            'wikimedia_editor_tasks_counts',
112            'wetc_count',
113            [
114                'wetc_user' => $centralId,
115                'wetc_key_id' => $keyId,
116                'wetc_lang' => $lang,
117            ],
118            __METHOD__
119        );
120    }
121
122    /**
123     * Delete counts for all languages for a single key and user.
124     * @param int $centralId central user ID
125     * @param int $keyId ID for counter key
126     * @return bool true if no exception was thrown
127     */
128    public function deleteAllCountsForKey( $centralId, $keyId ) {
129        return $this->dbw->delete(
130            'wikimedia_editor_tasks_counts',
131            [
132                'wetc_user' => $centralId,
133                'wetc_key_id' => $keyId,
134            ],
135            __METHOD__
136        );
137    }
138
139    /**
140     * Increment a user's count for a key and language.
141     * @param int $centralId central user ID
142     * @param int $keyId
143     * @param string $lang language code for this count
144     * @return bool true if no exception was thrown
145     */
146    public function incrementEditCountForKeyAndLang( $centralId, $keyId, $lang ) {
147        return $this->dbw->update(
148            'wikimedia_editor_tasks_counts',
149            [ 'wetc_count = wetc_count + 1' ],
150            [
151                'wetc_user' => $centralId,
152                'wetc_key_id' => $keyId,
153                'wetc_lang' => $lang,
154            ],
155            __METHOD__
156        );
157    }
158
159    /**
160     * Decrement a user's count for a key and language.
161     * @param int $centralId central user ID
162     * @param int $keyId
163     * @param string $lang language code for this count
164     * @return bool true if no exception was thrown
165     */
166    public function decrementEditCountForKeyAndLang( $centralId, $keyId, $lang ) {
167        return $this->dbw->update(
168            'wikimedia_editor_tasks_counts',
169            [ 'wetc_count = wetc_count - 1' ],
170            [
171                'wetc_user' => $centralId,
172                'wetc_key_id' => $keyId,
173                'wetc_lang' => $lang,
174                'wetc_count > 0'
175            ],
176            __METHOD__
177        );
178    }
179
180    /**
181     * Set the count for a given counter.
182     * @param int $centralId central user ID
183     * @param int $keyId counter key ID
184     * @param string $lang language code for this count
185     * @param int $count new count
186     */
187    public function setEditCountForKeyAndLang( $centralId, $keyId, $lang, $count ) {
188        $this->dbw->upsert(
189            'wikimedia_editor_tasks_counts',
190            [
191                'wetc_user' => $centralId,
192                'wetc_key_id' => $keyId,
193                'wetc_lang' => $lang,
194                'wetc_count' => $count,
195            ],
196            [ [ 'wetc_user', 'wetc_key_id', 'wetc_lang' ] ],
197            [ 'wetc_count = wetc_count + ' . (int)$count ],
198            __METHOD__
199        );
200    }
201
202    /**
203     * Get the edit streak length and last edit time for the user
204     * @param int $centralId central user ID
205     * @return array[] An array contains current streak length and last edit time
206     */
207    public function getEditStreak( $centralId ) {
208        $wrapper = $this->dbr->selectRow(
209            [ 'wikimedia_editor_tasks_edit_streak' ],
210            [ 'wetes_streak_length', 'wetes_last_edit_time' ],
211            [ 'wetes_user' => $centralId ],
212            __METHOD__
213        );
214        $result = [];
215        if ( $wrapper != false ) {
216            $result['length'] = (int)$wrapper->wetes_streak_length;
217            $result['last_edit_time'] = $wrapper->wetes_last_edit_time;
218        }
219        return $result;
220    }
221
222    /**
223     * Set the edit streak for a user.
224     * Increase the edit streak length if the user makes an edit within 2 days.
225     * @param int $centralId central user ID
226     */
227    public function setEditStreak( $centralId ) {
228        $currentTime = $this->dbw->timestamp( time() );
229        $this->dbw->upsert(
230            'wikimedia_editor_tasks_edit_streak',
231            [
232                'wetes_user' => $centralId,
233                'wetes_streak_length' => 1,
234                'wetes_last_edit_time' => $currentTime,
235            ],
236            'wetes_user',
237            [
238                'wetes_streak_length = IF (
239                    DATEDIFF ( ' . $currentTime . ', wetes_last_edit_time ) >= 2,
240                    1,
241                    IF (
242                        DATEDIFF ( ' . $currentTime . ', wetes_last_edit_time ) = 1,
243                        wetes_streak_length + 1,
244                        wetes_streak_length
245                    )
246                )',
247                'wetes_last_edit_time = ' . $currentTime
248            ],
249            __METHOD__
250        );
251    }
252
253    /**
254     * Increment a user's revert count for a key and language.
255     * @param int $centralId central user ID
256     * @param int $keyId
257     * @param string $lang language code for this count
258     * @return bool true if no exception was thrown
259     */
260    public function incrementRevertCountForKeyAndLang( $centralId, $keyId, $lang ) {
261        return $this->dbw->update(
262            'wikimedia_editor_tasks_counts',
263            [ 'wetc_revert_count = wetc_revert_count + 1' ],
264            [
265                'wetc_user' => $centralId,
266                'wetc_key_id' => $keyId,
267                'wetc_lang' => $lang,
268            ],
269            __METHOD__
270        );
271    }
272
273    /**
274     * Get all stored reverts counts by lang for the user.
275     * @param int $centralId central user ID
276     * @return array[] All counts in the form:
277     * [
278     *     <counter key> => [
279     *         <language code> => <count>,
280     *         ...
281     *     ],
282     *     ...
283     * ]
284     */
285    public function getAllRevertCounts( $centralId ) {
286        $wrapper = $this->dbr->select(
287            [ 'wikimedia_editor_tasks_counts', 'wikimedia_editor_tasks_keys' ],
288            [ 'wet_key', 'wetc_lang', 'wetc_revert_count' ],
289            [ 'wetc_user' => $centralId ],
290            __METHOD__,
291            [],
292            [
293                'wikimedia_editor_tasks_keys' => [
294                    'LEFT JOIN',
295                    'wet_id=wetc_key_id',
296                ],
297            ]
298        );
299        $result = [];
300        foreach ( $wrapper as $row ) {
301            $result[$row->wet_key][$row->wetc_lang] = (int)$row->wetc_revert_count;
302        }
303        return $result;
304    }
305
306    /**
307     * Get a single revert count by key and lang for a user.
308     * @param int $centralId central user ID
309     * @param int $keyId counter key ID
310     * @param string $lang language code
311     * @return int revert count for the specified key (returns 0 if not found)
312     */
313    public function getRevertCountForKeyAndLang( $centralId, $keyId, $lang ) {
314        return (int)$this->dbr->selectField(
315            'wikimedia_editor_tasks_counts',
316            'wetc_revert_count',
317            [
318                'wetc_user' => $centralId,
319                'wetc_key_id' => $keyId,
320                'wetc_lang' => $lang,
321            ],
322            __METHOD__
323        );
324    }
325}