GlobalContribs::globalEdits()   B
last analyzed

Complexity

Conditions 6
Paths 5

Size

Total Lines 42
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 24
nc 5
nop 0
dl 0
loc 42
rs 8.9137
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace App\Model;
6
7
use App\Repository\EditRepository;
8
use App\Repository\GlobalContribsRepository;
9
use App\Repository\PageRepository;
10
use App\Repository\UserRepository;
11
12
/**
13
 * A GlobalContribs provides a list of a user's edits to all projects.
14
 */
15
class GlobalContribs extends Model
16
{
17
    protected EditRepository $editRepo;
18
    protected PageRepository $pageRepo;
19
    protected UserRepository $userRepo;
20
21
    /** @var int Number of results per page. */
22
    public const PAGE_SIZE = 50;
23
24
    /** @var int[] Keys are project DB names. */
25
    protected array $globalEditCounts;
26
27
    /** @var array Most recent revisions across all projects. */
28
    protected array $globalEdits;
29
30
    /**
31
     * GlobalContribs constructor.
32
     * @param GlobalContribsRepository $repository
33
     * @param PageRepository $pageRepo
34
     * @param UserRepository $userRepo
35
     * @param EditRepository $editRepo
36
     * @param User $user
37
     * @param string|int|null $namespace Namespace ID or 'all'.
38
     * @param false|int $start As Unix timestamp.
39
     * @param false|int $end As Unix timestamp.
40
     * @param false|int $offset As Unix timestamp.
41
     * @param int|null $limit Number of results to return.
42
     */
43
    public function __construct(
44
        GlobalContribsRepository $repository,
45
        PageRepository $pageRepo,
46
        UserRepository $userRepo,
47
        EditRepository $editRepo,
48
        User $user,
49
        $namespace = 'all',
50
        $start = false,
51
        $end = false,
52
        $offset = false,
53
        ?int $limit = null
54
    ) {
55
        $this->repository = $repository;
56
        $this->pageRepo = $pageRepo;
57
        $this->userRepo = $userRepo;
58
        $this->editRepo = $editRepo;
59
        $this->user = $user;
60
        $this->namespace = '' == $namespace ? 0 : $namespace;
61
        $this->start = $start;
62
        $this->end = $end;
63
        $this->offset = $offset;
64
        $this->limit = $limit ?? self::PAGE_SIZE;
65
    }
66
67
    /**
68
     * Get the total edit counts for the top n projects of this user.
69
     * @param int $numProjects
70
     * @return array Each element has 'total' and 'project' keys.
71
     */
72
    public function globalEditCountsTopN(int $numProjects = 10): array
73
    {
74
        // Get counts.
75
        $editCounts = $this->globalEditCounts(true);
76
        // Truncate, and return.
77
        return array_slice($editCounts, 0, $numProjects);
78
    }
79
80
    /**
81
     * Get the total number of edits excluding the top n.
82
     * @param int $numProjects
83
     * @return int
84
     */
85
    public function globalEditCountWithoutTopN(int $numProjects = 10): int
86
    {
87
        $editCounts = $this->globalEditCounts(true);
88
        $bottomM = array_slice($editCounts, $numProjects);
89
        $total = 0;
90
        foreach ($bottomM as $editCount) {
91
            $total += $editCount['total'];
92
        }
93
        return $total;
94
    }
95
96
    /**
97
     * Get the grand total of all edits on all projects.
98
     * @return int
99
     */
100
    public function globalEditCount(): int
101
    {
102
        $total = 0;
103
        foreach ($this->globalEditCounts() as $editCount) {
104
            $total += $editCount['total'];
105
        }
106
        return $total;
107
    }
108
109
    /**
110
     * Get the total revision counts for all projects for this user.
111
     * @param bool $sorted Whether to sort the list by total, or not.
112
     * @return array[] Each element has 'total' and 'project' keys.
113
     */
114
    public function globalEditCounts(bool $sorted = false): array
115
    {
116
        if (!isset($this->globalEditCounts)) {
117
            $this->globalEditCounts = $this->repository->globalEditCounts($this->user);
0 ignored issues
show
Bug introduced by
The method globalEditCounts() does not exist on App\Repository\Repository. It seems like you code against a sub-type of App\Repository\Repository such as App\Repository\GlobalContribsRepository. ( Ignorable by Annotation )

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

117
            /** @scrutinizer ignore-call */ 
118
            $this->globalEditCounts = $this->repository->globalEditCounts($this->user);
Loading history...
118
        }
119
120
        if ($sorted) {
121
            // Sort.
122
            uasort($this->globalEditCounts, function ($a, $b) {
123
                return $b['total'] - $a['total'];
124
            });
125
        }
126
127
        return $this->globalEditCounts;
128
    }
129
130
    public function numProjectsWithEdits(): int
131
    {
132
        return count($this->repository->getProjectsWithEdits($this->user));
0 ignored issues
show
Bug introduced by
The method getProjectsWithEdits() does not exist on App\Repository\Repository. It seems like you code against a sub-type of App\Repository\Repository such as App\Repository\GlobalContribsRepository. ( Ignorable by Annotation )

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

132
        return count($this->repository->/** @scrutinizer ignore-call */ getProjectsWithEdits($this->user));
Loading history...
133
    }
134
135
    /**
136
     * Get the most recent revisions across all projects.
137
     * @return Edit[]
138
     */
139
    public function globalEdits(): array
140
    {
141
        if (isset($this->globalEdits)) {
142
            return $this->globalEdits;
143
        }
144
145
        // Get projects with edits.
146
        $projects = $this->repository->getProjectsWithEdits($this->user);
147
        if (0 === count($projects)) {
148
            return [];
149
        }
150
151
        // Get all revisions for those projects.
152
        $globalContribsRepo = $this->repository;
153
        $globalRevisionsData = $globalContribsRepo->getRevisions(
0 ignored issues
show
Bug introduced by
The method getRevisions() does not exist on App\Repository\Repository. It seems like you code against a sub-type of App\Repository\Repository such as App\Repository\GlobalContribsRepository or App\Repository\PageRepository or App\Repository\EditSummaryRepository. ( Ignorable by Annotation )

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

153
        /** @scrutinizer ignore-call */ 
154
        $globalRevisionsData = $globalContribsRepo->getRevisions(
Loading history...
154
            array_keys($projects),
155
            $this->user,
156
            $this->namespace,
157
            $this->start,
158
            $this->end,
159
            $this->limit + 1,
160
            $this->offset
161
        );
162
        $globalEdits = [];
163
164
        foreach ($globalRevisionsData as $revision) {
165
            $project = $projects[$revision['dbName']];
166
167
            // Can happen if the project is given from CentralAuth API but the database is not being replicated.
168
            if (null === $project || !$project->exists()) {
169
                continue;
170
            }
171
172
            $edit = $this->getEditFromRevision($project, $revision);
173
            $globalEdits[$edit->getTimestamp()->getTimestamp().'-'.$edit->getId()] = $edit;
174
        }
175
176
        // Sort and prune, before adding more.
177
        krsort($globalEdits);
178
        $this->globalEdits = array_slice($globalEdits, 0, $this->limit);
179
180
        return $this->globalEdits;
181
    }
182
183
    private function getEditFromRevision(Project $project, array $revision): Edit
184
    {
185
        $page = Page::newFromRow($this->pageRepo, $project, $revision);
186
        return new Edit($this->editRepo, $this->userRepo, $page, $revision);
187
    }
188
}
189