Passed
Push — master ( ed4035...f2dd38 )
by MusikAnimal
10:32
created

GlobalContribs::getEditFromRevision()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

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

98
                ->/** @scrutinizer ignore-call */ globalEditCounts($this->user);
Loading history...
99
        }
100
101 1
        if ($sorted) {
102
            // Sort.
103
            uasort($this->globalEditCounts, function ($a, $b) {
104 1
                return $b['total'] - $a['total'];
105 1
            });
106
        }
107
108 1
        return $this->globalEditCounts;
109
    }
110
111
    public function numProjectsWithEdits(): int
112
    {
113
        return count($this->getRepository()->getProjectsWithEdits($this->user));
0 ignored issues
show
Bug introduced by
The method getProjectsWithEdits() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\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

113
        return count($this->getRepository()->/** @scrutinizer ignore-call */ getProjectsWithEdits($this->user));
Loading history...
114
    }
115
116
    /**
117
     * Get the most recent $this->limit revisions across all projects, offset by $this->offset.
118
     * @return Edit[]
119
     */
120 1
    public function globalEdits(): array
121
    {
122 1
        if (is_array($this->globalEdits)) {
0 ignored issues
show
introduced by
The condition is_array($this->globalEdits) is always true.
Loading history...
123
            return $this->globalEdits;
124
        }
125
126
        // Get projects with edits.
127 1
        $projects = $this->getRepository()->getProjectsWithEdits($this->user);
128 1
        if (0 === count($projects)) {
129
            return [];
130
        }
131
132
        // Get all revisions for those projects.
133 1
        $globalRevisionsData = $this->getRepository()
134 1
            ->getRevisions(
135 1
                array_keys($projects),
136 1
                $this->user,
137 1
                $this->namespace,
138 1
                $this->start,
139 1
                $this->end,
140 1
                self::PAGE_SIZE + 1,
141 1
                $this->offset
142
            );
143 1
        $globalEdits = [];
144
145 1
        foreach ($globalRevisionsData as $revision) {
146
            /** @var Project $project */
147 1
            $project = $projects[$revision['dbName']];
148
149
            // Can happen if the project is given from CentralAuth API but the database is not being replicated.
150 1
            if (null === $project) {
151
                continue;
152
            }
153
154 1
            $edit = $this->getEditFromRevision($project, $revision);
155 1
            $globalEdits[$edit->getTimestamp()->getTimestamp().'-'.$edit->getId()] = $edit;
156
        }
157
158
        // Sort and prune, before adding more.
159 1
        krsort($globalEdits);
160 1
        $this->globalEdits = array_slice($globalEdits, 0, self::PAGE_SIZE);
161
162 1
        return $this->globalEdits;
163
    }
164
165 1
    private function getEditFromRevision(Project $project, array $revision): Edit
166
    {
167 1
        $nsName = '';
168 1
        if ($revision['page_namespace']) {
169 1
            $nsName = $project->getNamespaces()[$revision['page_namespace']];
170
        }
171
172 1
        $page = $project->getRepository()
173 1
            ->getPage($project, ltrim($nsName.':'.$revision['page_title'], ':'));
0 ignored issues
show
Bug introduced by
The method getPage() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\ProjectRepository. ( Ignorable by Annotation )

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

173
            ->/** @scrutinizer ignore-call */ getPage($project, ltrim($nsName.':'.$revision['page_title'], ':'));
Loading history...
174 1
        return new Edit($page, $revision);
175
    }
176
}
177