Passed
Pull Request — main (#442)
by MusikAnimal
08:42 queued 04:18
created

EditCounterRepository::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 9
dl 0
loc 15
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types = 1);
4
5
namespace App\Repository;
6
7
use App\Model\Project;
8
use App\Model\User;
9
use GuzzleHttp\Client;
10
use Psr\Cache\CacheItemPoolInterface;
11
use Psr\Container\ContainerInterface;
12
use Psr\Log\LoggerInterface;
13
use Wikimedia\IPUtils;
14
15
/**
16
 * An EditCounterRepository is responsible for retrieving edit count information from the
17
 * databases and API. It doesn't do any post-processing of that information.
18
 * @codeCoverageIgnore
19
 */
20
class EditCounterRepository extends Repository
21
{
22
    protected AutoEditsRepository $autoEditsRepo;
23
    protected ProjectRepository $projectRepo;
24
    protected UserRightsRepository $userRightsRepo;
25
26
    /**
27
     * @param ContainerInterface $container
28
     * @param CacheItemPoolInterface $cache
29
     * @param Client $guzzle
30
     * @param LoggerInterface $logger
31
     * @param ProjectRepository $projectRepo
32
     * @param UserRightsRepository $userRightsRepo
33
     * @param AutoEditsRepository $autoEditsRepo
34
     * @param bool $isWMF
35
     * @param int $queryTimeout
36
     */
37
    public function __construct(
38
        ContainerInterface $container,
39
        CacheItemPoolInterface $cache,
40
        Client $guzzle,
41
        LoggerInterface $logger,
42
        ProjectRepository $projectRepo,
43
        UserRightsRepository $userRightsRepo,
44
        AutoEditsRepository $autoEditsRepo,
45
        bool $isWMF,
46
        int $queryTimeout
47
    ) {
48
        $this->projectRepo = $projectRepo;
49
        $this->userRightsRepo = $userRightsRepo;
50
        $this->autoEditsRepo = $autoEditsRepo;
51
        parent::__construct($container, $cache, $guzzle, $logger, $isWMF, $queryTimeout);
52
    }
53
54
    /**
55
     * Get data about revisions, pages, etc.
56
     * @param Project $project The project.
57
     * @param User $user The user.
58
     * @return string[] With keys: 'deleted', 'live', 'total', '24h', '7d', '30d',
59
     * '365d', 'small', 'large', 'with_comments', and 'minor_edits', ...
60
     */
61
    public function getPairData(Project $project, User $user): array
62
    {
63
        // Set up cache.
64
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_pairdata');
65
        if ($this->cache->hasItem($cacheKey)) {
66
            return $this->cache->getItem($cacheKey)->get();
67
        }
68
69
        // Prepare the queries and execute them.
70
        $archiveTable = $project->getTableName('archive');
71
        $revisionTable = $project->getTableName('revision');
72
73
        if ($user->isIpRange()) {
74
            $ipcTable = $project->getTableName('ip_changes');
75
            $ipcJoin = "JOIN $ipcTable ON ipc_rev_id = rev_id";
76
            $whereClause = "ipc_hex BETWEEN :startIp AND :endIp";
77
            $archiveQueries = '';
78
            $params = [];
79
            [$params['startIp'], $params['endIp']] = IPUtils::parseRange($user->getUsername());
80
        } else {
81
            $ipcJoin = '';
82
            $whereClause = 'rev_actor = :actorId';
83
            $params = ['actorId' => $user->getActorId($project)];
84
            $archiveQueries = "
85
                SELECT 'deleted' AS `key`, COUNT(ar_id) AS val FROM $archiveTable
86
                    WHERE ar_actor = :actorId
87
                ) UNION (
88
                SELECT 'edited-deleted' AS `key`, COUNT(DISTINCT ar_page_id) AS `val` FROM $archiveTable
89
                    WHERE ar_actor = :actorId
90
                ) UNION (
91
                SELECT 'created-deleted' AS `key`, COUNT(DISTINCT ar_page_id) AS `val` FROM $archiveTable
92
                    WHERE ar_actor = :actorId AND ar_parent_id = 0
93
                ) UNION (";
94
        }
95
96
        $sql = "
97
            ($archiveQueries
98
99
            -- Revision counts.
100
            SELECT 'live' AS `key`, COUNT(rev_id) AS val FROM $revisionTable
101
                $ipcJoin
102
                WHERE $whereClause
103
            ) UNION (
104
            SELECT 'day' AS `key`, COUNT(rev_id) AS val FROM $revisionTable
105
                $ipcJoin
106
                WHERE $whereClause AND rev_timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
107
            ) UNION (
108
            SELECT 'week' AS `key`, COUNT(rev_id) AS val FROM $revisionTable
109
                $ipcJoin
110
                WHERE $whereClause AND rev_timestamp >= DATE_SUB(NOW(), INTERVAL 1 WEEK)
111
            ) UNION (
112
            SELECT 'month' AS `key`, COUNT(rev_id) AS val FROM $revisionTable
113
                $ipcJoin
114
                WHERE $whereClause AND rev_timestamp >= DATE_SUB(NOW(), INTERVAL 1 MONTH)
115
            ) UNION (
116
            SELECT 'year' AS `key`, COUNT(rev_id) AS val FROM $revisionTable
117
                $ipcJoin
118
                WHERE $whereClause AND rev_timestamp >= DATE_SUB(NOW(), INTERVAL 1 YEAR)
119
            ) UNION (
120
            SELECT 'minor' AS `key`, COUNT(rev_id) AS val FROM $revisionTable
121
                $ipcJoin
122
                WHERE $whereClause AND rev_minor_edit = 1
123
124
            -- Page counts.
125
            ) UNION (
126
            SELECT 'edited-live' AS `key`, COUNT(DISTINCT rev_page) AS `val`
127
                FROM $revisionTable
128
                $ipcJoin
129
                WHERE $whereClause
130
            ) UNION (
131
            SELECT 'created-live' AS `key`, COUNT(DISTINCT rev_page) AS `val`
132
                FROM $revisionTable
133
                $ipcJoin
134
                WHERE $whereClause AND rev_parent_id = 0
135
            )";
136
137
        $resultQuery = $this->executeProjectsQuery($project, $sql, $params);
138
139
        $revisionCounts = [];
140
        while ($result = $resultQuery->fetchAssociative()) {
141
            $revisionCounts[$result['key']] = (int)$result['val'];
142
        }
143
144
        // Cache and return.
145
        return $this->setCache($cacheKey, $revisionCounts);
146
    }
147
148
    /**
149
     * Get log totals for a user.
150
     * @param Project $project The project.
151
     * @param User $user The user.
152
     * @return int[] Keys are "<log>-<action>" strings, values are counts.
153
     */
154
    public function getLogCounts(Project $project, User $user): array
155
    {
156
        // Set up cache.
157
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_logcounts');
158
        if ($this->cache->hasItem($cacheKey)) {
159
            return $this->cache->getItem($cacheKey)->get();
160
        }
161
162
        // Query.
163
        $loggingTable = $this->getTableName($project->getDatabaseName(), 'logging');
164
        $sql = "
165
        (SELECT CONCAT(log_type, '-', log_action) AS source, COUNT(log_id) AS value
166
            FROM $loggingTable
167
            WHERE log_actor = :actorId
168
            GROUP BY log_type, log_action
169
        )";
170
171
        $results = $this->executeProjectsQuery($project, $sql, [
172
            'actorId' => $user->getActorId($project),
173
        ])->fetchAllAssociative();
174
175
        $logCounts = array_combine(
176
            array_map(function ($e) {
177
                return $e['source'];
178
            }, $results),
179
            array_map(function ($e) {
180
                return (int)$e['value'];
181
            }, $results)
182
        );
183
184
        // Make sure there is some value for each of the wanted counts.
185
        $requiredCounts = [
186
            'thanks-thank',
187
            'review-approve',
188
            'newusers-create2',
189
            'newusers-byemail',
190
            'patrol-patrol',
191
            'block-block',
192
            'block-reblock',
193
            'block-unblock',
194
            'protect-protect',
195
            'protect-modify',
196
            'protect-unprotect',
197
            'rights-rights',
198
            'move-move',
199
            'delete-delete',
200
            'delete-revision',
201
            'delete-restore',
202
            'import-import',
203
            'import-interwiki',
204
            'import-upload',
205
            'upload-upload',
206
            'upload-overwrite',
207
            'abusefilter-modify',
208
            'merge-merge',
209
            'contentmodel-change',
210
            'contentmodel-new',
211
        ];
212
        foreach ($requiredCounts as $req) {
213
            if (!isset($logCounts[$req])) {
214
                $logCounts[$req] = 0;
215
            }
216
        }
217
218
        // Cache and return.
219
        return $this->setCache($cacheKey, $logCounts);
220
    }
221
222
    /**
223
     * Get counts of files moved, and files moved/uploaded on Commons.
224
     * Local file uploads are counted in getLogCounts() since we're querying the same rows anyway.
225
     * @param Project $project
226
     * @param User $user
227
     * @return array
228
     */
229
    public function getFileCounts(Project $project, User $user): array
230
    {
231
        // Anons can't upload or move files.
232
        if ($user->isAnon()) {
233
            return [];
234
        }
235
236
        // Set up cache.
237
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_filecounts');
238
        if ($this->cache->hasItem($cacheKey)) {
239
            return $this->cache->getItem($cacheKey)->get();
240
        }
241
242
        $loggingTable = $project->getTableName('logging');
243
244
        $sql = "SELECT 'files_moved' AS `key`, COUNT(log_id) AS `val`
245
                FROM $loggingTable
246
                WHERE log_actor = :actorId
247
                    AND log_type = 'move'
248
                    AND log_action = 'move'
249
                    AND log_namespace = 6";
250
        $results = $this->executeProjectsQuery($project, $sql, [
251
            'actorId' => $user->getActorId($project),
252
        ])->fetchAllAssociative();
253
254
        if ($this->isWMF && 'commons.wikimedia.org' !== $project->getDomain()) {
255
            $results = array_merge($results, $this->getFileCountsCommons($user));
256
        }
257
258
        $counts = array_combine(
259
            array_map(function ($e) {
260
                return $e['key'];
261
            }, $results),
262
            array_map(function ($e) {
263
                return (int)$e['val'];
264
            }, $results)
265
        );
266
267
        // Cache and return.
268
        return $this->setCache($cacheKey, $counts);
269
    }
270
271
    /**
272
     * Get count of files moved and uploaded on Commons.
273
     * @param User $user
274
     * @return array
275
     */
276
    protected function getFileCountsCommons(User $user): array
277
    {
278
        $commonsProject = $this->projectRepo->getProject('commonswiki', $this->container);
0 ignored issues
show
Unused Code introduced by
The call to App\Repository\ProjectRepository::getProject() has too many arguments starting with $this->container. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

278
        /** @scrutinizer ignore-call */ 
279
        $commonsProject = $this->projectRepo->getProject('commonswiki', $this->container);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
279
        $loggingTableCommons = $commonsProject->getTableName('logging');
280
        $sql = "(SELECT 'files_moved_commons' AS `key`, COUNT(log_id) AS `val`
281
                 FROM $loggingTableCommons
282
                 WHERE log_actor = :actorId AND log_type = 'move'
283
                 AND log_action = 'move' AND log_namespace = 6
284
                ) UNION (
285
                 SELECT 'files_uploaded_commons' AS `key`, COUNT(log_id) AS `val`
286
                 FROM $loggingTableCommons
287
                 WHERE log_actor = :actorId AND log_type = 'upload' AND log_action = 'upload')";
288
        return $this->executeProjectsQuery($commonsProject, $sql, [
289
            'actorId' => $user->getActorId($commonsProject),
290
        ])->fetchAllAssociative();
291
    }
292
293
    /**
294
     * Get the IDs and timestamps of the latest edit and logged action by the given user.
295
     * @param Project $project
296
     * @param User $user
297
     * @return string[] With keys 'rev_first', 'rev_latest', 'log_latest'.
298
     */
299
    public function getFirstAndLatestActions(Project $project, User $user): array
300
    {
301
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_first_latest_actions');
302
        if ($this->cache->hasItem($cacheKey)) {
303
            return $this->cache->getItem($cacheKey)->get();
304
        }
305
306
        $loggingTable = $project->getTableName('logging', 'userindex');
307
        if ($user->isIpRange()) {
308
            $fromTable = $project->getTableName('ip_changes');
309
            $idColumn = 'ipc_rev_id';
310
            $timestampColumn = 'ipc_rev_timestamp';
311
            $whereClause = "ipc_hex BETWEEN :startIp AND :endIp";
312
            $params = [];
313
            [$params['startIp'], $params['endIp']] = IPUtils::parseRange($user->getUsername());
314
            $logQuery = '';
315
        } else {
316
            $fromTable = $project->getTableName('revision');
317
            $idColumn = 'rev_id';
318
            $timestampColumn = 'rev_timestamp';
319
            $whereClause = 'rev_actor = :actorId';
320
            $params = ['actorId' => $user->getActorId($project)];
321
            $logQuery = "
322
                SELECT 'log_latest' AS `key`, log_id AS `id`,
323
                        log_timestamp AS `timestamp`, log_type AS `type`
324
                    FROM $loggingTable
325
                    WHERE log_actor = :actorId
326
                    ORDER BY log_timestamp DESC LIMIT 1
327
                ) UNION (";
328
        }
329
330
        $sql = "(
331
                $logQuery
332
                    SELECT 'rev_first' AS `key`, $idColumn AS `id`,
333
                        $timestampColumn AS `timestamp`, NULL as `type`
334
                    FROM $fromTable
335
                    WHERE $whereClause
336
                    ORDER BY $timestampColumn ASC LIMIT 1
337
                ) UNION (
338
                    SELECT 'rev_latest' AS `key`, $idColumn AS `id`,
339
                        $timestampColumn AS `timestamp`, NULL as `type`
340
                    FROM $fromTable
341
                    WHERE $whereClause
342
                    ORDER BY $timestampColumn DESC LIMIT 1
343
                )";
344
345
        $resultQuery = $this->executeProjectsQuery($project, $sql, $params);
346
347
        $actions = [];
348
        while ($result = $resultQuery->fetchAssociative()) {
349
            $actions[$result['key']] = [
350
                'id' => $result['id'],
351
                'timestamp' => $result['timestamp'],
352
                'type' => $result['type'],
353
            ];
354
        }
355
356
        return $this->setCache($cacheKey, $actions);
357
    }
358
359
    /**
360
     * Get data for all blocks set on the given user.
361
     * @param Project $project
362
     * @param User $user
363
     * @return array
364
     */
365
    public function getBlocksReceived(Project $project, User $user): array
366
    {
367
        $loggingTable = $this->getTableName($project->getDatabaseName(), 'logging', 'logindex');
368
        $sql = "SELECT log_action, log_timestamp, log_params FROM $loggingTable
369
                WHERE log_type = 'block'
370
                AND log_action IN ('block', 'reblock', 'unblock')
371
                AND log_timestamp > 0
372
                AND log_title = :username
373
                AND log_namespace = 2
374
                ORDER BY log_timestamp ASC";
375
        $username = str_replace(' ', '_', $user->getUsername());
376
377
        return $this->executeProjectsQuery($project, $sql, [
378
            'username' => $username,
379
        ])->fetchAllAssociative();
380
    }
381
382
    /**
383
     * Get the number of times the user was thanked.
384
     * @param Project $project
385
     * @param User $user
386
     * @return int
387
     */
388
    public function getThanksReceived(Project $project, User $user): int
389
    {
390
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_thanksreceived');
391
        if ($this->cache->hasItem($cacheKey)) {
392
            return $this->cache->getItem($cacheKey)->get();
393
        }
394
395
        $loggingTable = $project->getTableName('logging', 'logindex');
396
        $sql = "SELECT COUNT(log_id)
397
                FROM $loggingTable
398
                WHERE log_type = 'thanks'
399
                AND log_title = :username
400
                AND log_namespace = 2";
401
        $username = str_replace(' ', '_', $user->getUsername());
402
403
        return $this->setCache($cacheKey, (int)$this->executeProjectsQuery($project, $sql, [
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...y\Result::fetchColumn() has been deprecated: Use fetchOne() instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

403
        return $this->setCache($cacheKey, (int)/** @scrutinizer ignore-deprecated */ $this->executeProjectsQuery($project, $sql, [

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
404
            'username' => $username,
405
        ])->fetchColumn());
406
    }
407
408
    /**
409
     * Get the given user's total edit counts per namespace on the given project.
410
     * @param Project $project The project.
411
     * @param User $user The user.
412
     * @return array Array keys are namespace IDs, values are the edit counts.
413
     */
414
    public function getNamespaceTotals(Project $project, User $user): array
415
    {
416
        // Cache?
417
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_namespacetotals');
418
        if ($this->cache->hasItem($cacheKey)) {
419
            return $this->cache->getItem($cacheKey)->get();
420
        }
421
422
        // Query.
423
        $revisionTable = $project->getTableName('revision');
424
        $pageTable = $project->getTableName('page');
425
        $ipcJoin = '';
426
        $whereClause = 'r.rev_actor = :actorId';
427
        $params = ['actorId' => $user->getActorId($project)];
428
429
        if ($user->isIpRange()) {
430
            $ipcTable = $project->getTableName('ip_changes');
431
            $ipcJoin = "JOIN $ipcTable ON ipc_rev_id = rev_id";
432
            [$params['startIp'], $params['endIp']] = IPUtils::parseRange($user->getUsername());
433
            $whereClause = 'ipc_hex BETWEEN :startIp AND :endIp';
434
        }
435
436
        $sql = "SELECT page_namespace, COUNT(rev_id) AS total
437
            FROM $pageTable p JOIN $revisionTable r ON (r.rev_page = p.page_id)
438
            $ipcJoin
439
            WHERE $whereClause
440
            GROUP BY page_namespace";
441
442
        $results = $this->executeProjectsQuery($project, $sql, $params)->fetchAll();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

442
        $results = /** @scrutinizer ignore-deprecated */ $this->executeProjectsQuery($project, $sql, $params)->fetchAll();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
443
444
        $namespaceTotals = array_combine(array_map(function ($e) {
445
            return $e['page_namespace'];
446
        }, $results), array_map(function ($e) {
447
            return (int)$e['total'];
448
        }, $results));
449
450
        // Cache and return.
451
        return $this->setCache($cacheKey, $namespaceTotals);
452
    }
453
454
    /**
455
     * Get data for a bar chart of monthly edit totals per namespace.
456
     * @param Project $project The project.
457
     * @param User $user The user.
458
     * @return string[] [
459
     *                      [
460
     *                          'year' => <year>,
461
     *                          'month' => <month>,
462
     *                          'page_namespace' => <namespace>,
463
     *                          'count' => <count>,
464
     *                      ],
465
     *                      ...
466
     *                  ]
467
     */
468
    public function getMonthCounts(Project $project, User $user): array
469
    {
470
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_monthcounts');
471
        if ($this->cache->hasItem($cacheKey)) {
472
            return $this->cache->getItem($cacheKey)->get();
473
        }
474
475
        $revisionTable = $project->getTableName('revision');
476
        $pageTable = $project->getTableName('page');
477
        $ipcJoin = '';
478
        $whereClause = 'rev_actor = :actorId';
479
        $params = ['actorId' => $user->getActorId($project)];
480
481
        if ($user->isIpRange()) {
482
            $ipcTable = $project->getTableName('ip_changes');
483
            $ipcJoin = "JOIN $ipcTable ON ipc_rev_id = rev_id";
484
            [$params['startIp'], $params['endIp']] = IPUtils::parseRange($user->getUsername());
485
            $whereClause = 'ipc_hex BETWEEN :startIp AND :endIp';
486
        }
487
488
        $sql = "
489
            SELECT YEAR(rev_timestamp) AS `year`,
490
                MONTH(rev_timestamp) AS `month`,
491
                page_namespace,
492
                COUNT(rev_id) AS `count`
493
            FROM $revisionTable JOIN $pageTable ON (rev_page = page_id)
494
            $ipcJoin
495
            WHERE $whereClause
496
            GROUP BY YEAR(rev_timestamp), MONTH(rev_timestamp), page_namespace";
497
498
        $totals = $this->executeProjectsQuery($project, $sql, $params)->fetchAll();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

498
        $totals = /** @scrutinizer ignore-deprecated */ $this->executeProjectsQuery($project, $sql, $params)->fetchAll();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
499
500
        // Cache and return.
501
        return $this->setCache($cacheKey, $totals);
502
    }
503
504
    /**
505
     * Get data for the timecard chart, with totals grouped by day and to the nearest two-hours.
506
     * @param Project $project
507
     * @param User $user
508
     * @return string[][]
509
     */
510
    public function getTimeCard(Project $project, User $user): array
511
    {
512
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_timecard');
513
        if ($this->cache->hasItem($cacheKey)) {
514
            return $this->cache->getItem($cacheKey)->get();
515
        }
516
517
        $hourInterval = 1;
518
519
        if ($user->isIpRange()) {
520
            $column = 'ipc_rev_timestamp';
521
            $table = $project->getTableName('ip_changes');
522
            [$params['startIp'], $params['endIp']] = IPUtils::parseRange($user->getUsername());
523
            $whereClause = 'ipc_hex BETWEEN :startIp AND :endIp';
524
        } else {
525
            $column = 'rev_timestamp';
526
            $table = $project->getTableName('revision');
527
            $whereClause = 'rev_actor = :actorId';
528
            $params = ['actorId' => $user->getActorId($project)];
529
        }
530
531
        $xCalc = "ROUND(HOUR($column)/$hourInterval) * $hourInterval";
532
533
        $sql = "
534
            SELECT DAYOFWEEK($column) AS `day_of_week`,
535
                $xCalc AS `hour`,
536
                COUNT($column) AS `value`
537
            FROM $table
538
            WHERE $whereClause
539
            GROUP BY DAYOFWEEK($column), $xCalc";
540
541
        $totals = $this->executeProjectsQuery($project, $sql, $params)->fetchAll();
0 ignored issues
show
Deprecated Code introduced by
The function Doctrine\DBAL\ForwardCom...lity\Result::fetchAll() has been deprecated: Use fetchAllNumeric(), fetchAllAssociative() or fetchFirstColumn() instead. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

541
        $totals = /** @scrutinizer ignore-deprecated */ $this->executeProjectsQuery($project, $sql, $params)->fetchAll();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
542
543
        // Cache and return.
544
        return $this->setCache($cacheKey, $totals);
545
    }
546
547
    /**
548
     * Get various data about edit sizes of the past 5,000 edits.
549
     * Will cache the result for 10 minutes.
550
     * @param Project $project The project.
551
     * @param User $user The user.
552
     * @return string[] Values with for keys 'average_size',
553
     *                  'small_edits' and 'large_edits'
554
     */
555
    public function getEditSizeData(Project $project, User $user): array
556
    {
557
        // Set up cache.
558
        $cacheKey = $this->getCacheKey(func_get_args(), 'ec_editsizes');
559
        if ($this->cache->hasItem($cacheKey)) {
560
            return $this->cache->getItem($cacheKey)->get();
561
        }
562
563
        // Prepare the queries and execute them.
564
        $revisionTable = $project->getTableName('revision');
565
        $ipcJoin = '';
566
        $whereClause = 'revs.rev_actor = :actorId';
567
        $params = ['actorId' => $user->getActorId($project)];
568
569
        if ($user->isIpRange()) {
570
            $ipcTable = $project->getTableName('ip_changes');
571
            $ipcJoin = "JOIN $ipcTable ON ipc_rev_id = revs.rev_id";
572
            [$params['startIp'], $params['endIp']] = IPUtils::parseRange($user->getUsername());
573
            $whereClause = 'ipc_hex BETWEEN :startIp AND :endIp';
574
        }
575
576
        $sql = "SELECT AVG(sizes.size) AS average_size,
577
                COUNT(CASE WHEN sizes.size < 20 THEN 1 END) AS small_edits,
578
                COUNT(CASE WHEN sizes.size > 1000 THEN 1 END) AS large_edits
579
                FROM (
580
                    SELECT (CAST(revs.rev_len AS SIGNED) - IFNULL(parentrevs.rev_len, 0)) AS size
581
                    FROM $revisionTable AS revs
582
                    $ipcJoin
583
                    LEFT JOIN $revisionTable AS parentrevs ON (revs.rev_parent_id = parentrevs.rev_id)
584
                    WHERE $whereClause
585
                    ORDER BY revs.rev_timestamp DESC
586
                    LIMIT 5000
587
                ) sizes";
588
        $results = $this->executeProjectsQuery($project, $sql, $params)->fetchAssociative();
589
590
        // Cache and return.
591
        return $this->setCache($cacheKey, $results);
592
    }
593
594
    /**
595
     * Get the number of edits this user made using semi-automated tools.
596
     * @param Project $project
597
     * @param User $user
598
     * @return int Result of query, see below.
599
     * @deprecated Inject AutoEditsRepository and call the countAutomatedEdits directly.
600
     */
601
    public function countAutomatedEdits(Project $project, User $user): int
602
    {
603
        return $this->autoEditsRepo->countAutomatedEdits($project, $user);
604
    }
605
}
606