Passed
Push — master ( 9c80d9...628b52 )
by MusikAnimal
05:31
created

AutoEdits::getOffset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the AutoEdits class.
4
 */
5
6
namespace Xtools;
7
8
/**
9
 * AutoEdits returns statistics about automated edits made by a user.
10
 */
11
class AutoEdits extends Model
12
{
13
    /** @var Project The project. */
14
    protected $project;
15
16
    /** @var User The user. */
17
    protected $user;
18
19
    /** @var int|string Which namespace we are querying for. */
20
    protected $namespace;
21
22
    /** @var string Start date. */
23
    protected $start;
24
25
    /** @var string End date. */
26
    protected $end;
27
28
    /** @var null|string The tool we're searching for when fetching (semi-)automated edits. */
29
    protected $tool;
30
31
    /** @var int Number of rows to OFFSET, used for pagination. */
32
    protected $offset;
33
34
    /** @var Edit[] The list of non-automated contributions. */
35
    protected $nonAutomatedEdits;
36
37
    /** @var Edit[] The list of automated contributions. */
38
    protected $automatedEdits;
39
40
    /** @var int Total number of edits. */
41
    protected $editCount;
42
43
    /** @var int Total number of non-automated edits. */
44
    protected $automatedCount;
45
46
    /** @var array Counts of known automated tools used by the given user. */
47
    protected $toolCounts;
48
49
    /** @var int Total number of edits made with the tools. */
50
    protected $toolsTotal;
51
52
    /**
53
     * Constructor for the AutoEdits class.
54
     * @param Project $project
55
     * @param User $user
56
     * @param int|string $namespace Namespace ID or 'all'
57
     * @param string $start Start date in a format accepted by strtotime()
58
     * @param string $end End date in a format accepted by strtotime()
59
     * @param string $tool The tool we're searching for when fetching (semi-)automated edits.
60
     * @param int $offset Used for pagination, offset results by N edits.
61
     */
62 5
    public function __construct(
63
        Project $project,
64
        User $user,
65
        $namespace = 'all',
66
        $start = '',
67
        $end = '',
68
        $tool = null,
69
        $offset = 0
70
    ) {
71 5
        $this->project = $project;
72 5
        $this->user = $user;
73 5
        $this->namespace = $namespace;
74 5
        $this->start = $start;
75 5
        $this->end = $end;
76 5
        $this->tool = $tool;
77 5
        $this->offset = $offset;
78 5
    }
79
80
    /**
81
     * Get the namespace.
82
     * @return int|string
83
     */
84 1
    public function getNamespace()
85
    {
86 1
        return $this->namespace;
87
    }
88
89
    /**
90
     * Get the start date.
91
     * @return string
92
     */
93 1
    public function getStart()
94
    {
95 1
        return $this->start;
96
    }
97
98
    /**
99
     * Get the end date.
100
     * @return string
101
     */
102 1
    public function getEnd()
103
    {
104 1
        return $this->end;
105
    }
106
107
    /**
108
     * The tool we're limiting the results to when fetching
109
     * (semi-)automated contributions.
110
     * @return null|string
111
     */
112 1
    public function getTool()
113
    {
114 1
        return $this->tool;
115
    }
116
117
    /**
118
     * Get the offset value.
119
     * @return int
120
     */
121 1
    public function getOffset()
122
    {
123 1
        return $this->offset;
124
    }
125
126
    /**
127
     * Get the raw edit count of the user.
128
     * @return int
129
     */
130 1
    public function getEditCount()
131
    {
132 1
        if (!is_int($this->editCount)) {
0 ignored issues
show
introduced by
The condition is_int($this->editCount) is always true.
Loading history...
133 1
            $this->editCount = $this->user->countEdits(
134 1
                $this->project,
135 1
                $this->namespace,
136 1
                $this->start,
137 1
                $this->end
138
            );
139
        }
140
141 1
        return $this->editCount;
142
    }
143
144
    /**
145
     * Get the number of edits this user made using semi-automated tools.
146
     * This is not the same as self::getToolCounts because the regex can overlap.
147
     * @return int Result of query, see below.
148
     */
149 1
    public function getAutomatedCount()
150
    {
151 1
        if (is_int($this->automatedCount)) {
0 ignored issues
show
introduced by
The condition is_int($this->automatedCount) is always true.
Loading history...
152 1
            return $this->automatedCount;
153
        }
154
155 1
        $this->automatedCount = (int)$this->getRepository()->countAutomatedEdits(
156 1
            $this->project,
157 1
            $this->user,
158 1
            $this->namespace,
159 1
            $this->start,
160 1
            $this->end
161
        );
162
163 1
        return $this->automatedCount;
164
    }
165
166
    /**
167
     * Get the percentage of all edits made using automated tools.
168
     * @return float
169
     */
170 1
    public function getAutomatedPercentage()
171
    {
172 1
        return $this->getEditCount() > 0
173 1
            ? ($this->getAutomatedCount() / $this->getEditCount()) * 100
174 1
            : 0;
175
    }
176
177
    /**
178
     * Get non-automated contributions for this user.
179
     * @param bool $raw Wether to return raw data from the database,
180
     *   or get Edit objects.
181
     * @return string[]|Edit[]
182
     */
183 1
    public function getNonAutomatedEdits($raw = false)
184
    {
185 1
        if (is_array($this->nonAutomatedEdits)) {
0 ignored issues
show
introduced by
The condition is_array($this->nonAutomatedEdits) is always true.
Loading history...
186 1
            return $this->nonAutomatedEdits;
187
        }
188
189 1
        $revs = $this->getRepository()->getNonAutomatedEdits(
190 1
            $this->project,
191 1
            $this->user,
192 1
            $this->namespace,
193 1
            $this->start,
194 1
            $this->end,
195 1
            $this->offset
196
        );
197
198 1
        if ($raw) {
199 1
            return $revs;
200
        }
201
202 1
        $this->nonAutomatedEdits = $this->getEditsFromRevs($revs);
203
204 1
        return $this->nonAutomatedEdits;
205
    }
206
207
    /**
208
     * Get automated contributions for this user.
209
     * @param bool $raw Wether to return raw data from the database,
210
     *   or get Edit objects.
211
     * @return Edit[]
212
     */
213 1
    public function getAutomatedEdits($raw = false)
214
    {
215 1
        if (is_array($this->automatedEdits)) {
0 ignored issues
show
introduced by
The condition is_array($this->automatedEdits) is always true.
Loading history...
216 1
            return $this->automatedEdits;
217
        }
218
219 1
        $revs = $this->getRepository()->getAutomatedEdits(
220 1
            $this->project,
221 1
            $this->user,
222 1
            $this->namespace,
223 1
            $this->start,
224 1
            $this->end,
225 1
            $this->tool,
226 1
            $this->offset
227
        );
228
229 1
        if ($raw) {
230 1
            return $revs;
231
        }
232
233 1
        $this->automatedEdits = $this->getEditsFromRevs($revs);
234
235 1
        return $this->automatedEdits;
236
    }
237
238
    /**
239
     * Transform database rows into Edit objects.
240
     * @param  string[] $revs
241
     * @return Edit[]
242
     */
243 2
    private function getEditsFromRevs(array $revs)
244
    {
245
        return array_map(function ($rev) {
246
            /* @var Page Page object to be passed to the Edit contructor. */
247 2
            $page = $this->getPageFromRev($rev);
248 2
            $rev['user'] = $this->user;
249
250 2
            return new Edit($page, $rev);
0 ignored issues
show
Bug introduced by
$page of type Xtools\Page[] is incompatible with the type Xtools\Page expected by parameter $page of Xtools\Edit::__construct(). ( Ignorable by Annotation )

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

250
            return new Edit(/** @scrutinizer ignore-type */ $page, $rev);
Loading history...
251 2
        }, $revs);
252
    }
253
254
    /**
255
     * Get a Page object given a revision row.
256
     * @param array $rev Revision as retrieved from the database.
257
     * @return Page[]
258
     */
259 2
    private function getPageFromRev(array $rev)
260
    {
261 2
        $namespaces = $this->project->getNamespaces();
262 2
        $pageTitle = $rev['page_title'];
263 2
        $fullPageTitle = '';
264
265 2
        if ((int)$rev['page_namespace'] === 0) {
266 1
            $fullPageTitle = $pageTitle;
267
        } else {
268 1
            $fullPageTitle = $namespaces[$rev['page_namespace']].":$pageTitle";
269
        }
270
271 2
        return new Page($this->project, $fullPageTitle);
272
    }
273
274
    /**
275
     * Get counts of known automated tools used by the given user.
276
     * @return string[] Each tool that they used along with the count and link:
277
     *                  [
278
     *                      'Twinkle' => [
279
     *                          'count' => 50,
280
     *                          'link' => 'Wikipedia:Twinkle',
281
     *                      ],
282
     *                  ]
283
     */
284 1
    public function getToolCounts()
285
    {
286 1
        if (is_array($this->toolCounts)) {
0 ignored issues
show
introduced by
The condition is_array($this->toolCounts) is always true.
Loading history...
287 1
            return $this->toolCounts;
288
        }
289
290 1
        $this->toolCounts = $this->getRepository()->getToolCounts(
291 1
            $this->project,
292 1
            $this->user,
293 1
            $this->namespace,
294 1
            $this->start,
295 1
            $this->end
296
        );
297
298 1
        return $this->toolCounts;
299
    }
300
301
    /**
302
     * Get the combined number of edits made with each tool. This is calculated
303
     * separately from self::getAutomatedCount() because the regex can sometimes
304
     * overlap, and the counts are actually different.
305
     * @return int
306
     */
307 1
    public function getToolsTotal()
308
    {
309 1
        if (!is_int($this->toolsTotal)) {
0 ignored issues
show
introduced by
The condition is_int($this->toolsTotal) is always true.
Loading history...
310 1
            $this->toolsTotal = array_reduce($this->getToolCounts(), function ($a, $b) {
311 1
                return $a + $b['count'];
312 1
            });
313
        }
314
315 1
        return $this->toolsTotal;
316
    }
317
}
318