|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* This file contains only the Pages class. |
|
4
|
|
|
*/ |
|
5
|
|
|
|
|
6
|
|
|
namespace Xtools; |
|
7
|
|
|
|
|
8
|
|
|
use Xtools\Project; |
|
9
|
|
|
use Xtools\User; |
|
10
|
|
|
use DateTime; |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* A Pages provides statistics about the pages created by a given User. |
|
14
|
|
|
*/ |
|
15
|
|
|
class Pages extends Model |
|
16
|
|
|
{ |
|
17
|
|
|
const RESULTS_LIMIT_SINGLE_NAMESPACE = 1000; |
|
18
|
|
|
const RESULTS_LIMIT_ALL_NAMESPACES = 100; |
|
19
|
|
|
|
|
20
|
|
|
/** @var Project The project. */ |
|
21
|
|
|
protected $project; |
|
22
|
|
|
|
|
23
|
|
|
/** @var User The user. */ |
|
24
|
|
|
protected $user; |
|
25
|
|
|
|
|
26
|
|
|
/** @var string Which namespace we are querying for. */ |
|
27
|
|
|
protected $namespace; |
|
28
|
|
|
|
|
29
|
|
|
/** @var string One of 'noredirects', 'onlyredirects' or blank for both. */ |
|
30
|
|
|
protected $redirects; |
|
31
|
|
|
|
|
32
|
|
|
/** @var int Pagination offset. */ |
|
33
|
|
|
protected $offset; |
|
34
|
|
|
|
|
35
|
|
|
/** @var array The list of pages including various statistics. */ |
|
36
|
|
|
protected $pages; |
|
37
|
|
|
|
|
38
|
|
|
/** @var array Number of redirects/pages that were created/deleted, broken down by namespace. */ |
|
39
|
|
|
protected $countsByNamespace; |
|
40
|
|
|
|
|
41
|
|
|
/** @var bool Whether or not the Project supports page assessments. */ |
|
42
|
|
|
protected $hasPageAssessments; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* Pages constructor. |
|
46
|
|
|
* @param Project $project |
|
47
|
|
|
* @param User $user |
|
48
|
|
|
* @param string|int $namespace Namespace ID or 'all'. |
|
49
|
|
|
* @param string $redirects One of 'noredirects', 'onlyredirects' or blank for both. |
|
50
|
|
|
* @param int $offset Pagination offset. |
|
51
|
|
|
*/ |
|
52
|
2 |
View Code Duplication |
public function __construct( |
|
|
|
|
|
|
53
|
|
|
Project $project, |
|
54
|
|
|
User $user, |
|
55
|
|
|
$namespace = 0, |
|
56
|
|
|
$redirects = 'noredirects', |
|
57
|
|
|
$offset = 0 |
|
58
|
|
|
) { |
|
59
|
2 |
|
$this->project = $project; |
|
60
|
2 |
|
$this->user = $user; |
|
61
|
2 |
|
$this->namespace = $namespace === 'all' ? 'all' : (string)$namespace; |
|
62
|
2 |
|
$this->redirects = $redirects; |
|
63
|
2 |
|
$this->offset = $offset; |
|
64
|
2 |
|
} |
|
65
|
|
|
|
|
66
|
|
|
/** |
|
67
|
|
|
* The project associated with this Pages instance. |
|
68
|
|
|
* @return Project |
|
69
|
|
|
*/ |
|
70
|
1 |
|
public function getProject() |
|
71
|
|
|
{ |
|
72
|
1 |
|
return $this->project; |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* The user associated with this Pages instance. |
|
77
|
|
|
* @return User |
|
78
|
|
|
*/ |
|
79
|
1 |
|
public function getUser() |
|
80
|
|
|
{ |
|
81
|
1 |
|
return $this->user; |
|
82
|
|
|
} |
|
83
|
|
|
|
|
84
|
|
|
/** |
|
85
|
|
|
* The namespace associated with this Pages instance. |
|
86
|
|
|
* @return int|string |
|
87
|
|
|
*/ |
|
88
|
1 |
|
public function getNamespace() |
|
89
|
|
|
{ |
|
90
|
1 |
|
return $this->namespace; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
/** |
|
94
|
|
|
* The redirects option associated with this Pages instance. |
|
95
|
|
|
* @return string |
|
96
|
|
|
*/ |
|
97
|
1 |
|
public function getRedirects() |
|
98
|
|
|
{ |
|
99
|
1 |
|
return $this->redirects; |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* The pagination offset associated with this Pages instance. |
|
104
|
|
|
* @return int |
|
105
|
|
|
*/ |
|
106
|
1 |
|
public function getOffset() |
|
107
|
|
|
{ |
|
108
|
1 |
|
return $this->offset; |
|
109
|
|
|
} |
|
110
|
|
|
|
|
111
|
|
|
/** |
|
112
|
|
|
* Fetch and prepare the pages created by the user. |
|
113
|
|
|
* @codeCoverageIgnore |
|
114
|
|
|
*/ |
|
115
|
|
|
public function prepareData() |
|
116
|
|
|
{ |
|
117
|
|
|
$this->pages = []; |
|
118
|
|
|
|
|
119
|
|
|
foreach ($this->getNamespaces() as $ns) { |
|
120
|
|
|
$data = $this->fetchPagesCreated($ns); |
|
121
|
|
|
$this->pages[$ns] = $this->formatPages($data)[$ns]; |
|
122
|
|
|
} |
|
123
|
|
|
|
|
124
|
|
|
return $this->pages; |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
/** |
|
128
|
|
|
* The public function to get the list of all pages created by the user, |
|
129
|
|
|
* up to self::resultsPerPage(), across all namespaces. |
|
130
|
|
|
* @return array |
|
131
|
|
|
*/ |
|
132
|
1 |
|
public function getResults() |
|
133
|
|
|
{ |
|
134
|
1 |
|
if ($this->pages === null) { |
|
135
|
|
|
$this->prepareData(); |
|
136
|
|
|
} |
|
137
|
1 |
|
return $this->pages; |
|
138
|
|
|
} |
|
139
|
|
|
|
|
140
|
|
|
/** |
|
141
|
|
|
* Get the total number of pages the user has created. |
|
142
|
|
|
* @return int |
|
143
|
|
|
*/ |
|
144
|
|
|
public function getNumPages() |
|
145
|
|
|
{ |
|
146
|
|
|
$total = 0; |
|
147
|
|
|
foreach ($this->getCounts() as $ns => $values) { |
|
148
|
|
|
$total += $values['count']; |
|
149
|
|
|
} |
|
150
|
|
|
return $total; |
|
151
|
|
|
} |
|
152
|
|
|
|
|
153
|
|
|
/** |
|
154
|
|
|
* Get the total number of pages we're showing data for. |
|
155
|
|
|
* @return int |
|
156
|
|
|
*/ |
|
157
|
1 |
|
public function getNumResults() |
|
158
|
|
|
{ |
|
159
|
1 |
|
$total = 0; |
|
160
|
1 |
|
foreach ($this->getResults() as $ns => $pages) { |
|
161
|
1 |
|
$total += count($pages); |
|
162
|
|
|
} |
|
163
|
1 |
|
return $total; |
|
164
|
|
|
} |
|
165
|
|
|
|
|
166
|
|
|
/** |
|
167
|
|
|
* Get the total number of pages that are currently deleted. |
|
168
|
|
|
* @return int |
|
169
|
|
|
*/ |
|
170
|
1 |
|
public function getNumDeleted() |
|
171
|
|
|
{ |
|
172
|
1 |
|
$total = 0; |
|
173
|
1 |
|
foreach ($this->getCounts() as $ns => $values) { |
|
174
|
1 |
|
$total += $values['deleted']; |
|
175
|
|
|
} |
|
176
|
1 |
|
return $total; |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* Get the total number of pages that are currently redirects. |
|
181
|
|
|
* @return int |
|
182
|
|
|
*/ |
|
183
|
1 |
|
public function getNumRedirects() |
|
184
|
|
|
{ |
|
185
|
1 |
|
$total = 0; |
|
186
|
1 |
|
foreach ($this->getCounts() as $ns => $values) { |
|
187
|
1 |
|
$total += $values['redirects']; |
|
188
|
|
|
} |
|
189
|
1 |
|
return $total; |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
/** |
|
193
|
|
|
* Get the namespaces in which this user has created pages. |
|
194
|
|
|
* @return string[] The IDs. |
|
195
|
|
|
*/ |
|
196
|
1 |
|
public function getNamespaces() |
|
197
|
|
|
{ |
|
198
|
1 |
|
return array_keys($this->getCounts()); |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
|
|
/** |
|
202
|
|
|
* Number of namespaces being reported. |
|
203
|
|
|
* @return int |
|
204
|
|
|
*/ |
|
205
|
|
|
public function getNumNamespaces() |
|
206
|
|
|
{ |
|
207
|
|
|
return count(array_keys($this->getCounts())); |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
/** |
|
211
|
|
|
* Number of redirects/pages that were created/deleted, broken down by namespace. |
|
212
|
|
|
* @return array Namespace IDs as the keys, with values 'count', 'deleted' and 'redirects'. |
|
213
|
|
|
*/ |
|
214
|
1 |
|
public function getCounts() |
|
215
|
|
|
{ |
|
216
|
1 |
|
if ($this->countsByNamespace !== null) { |
|
217
|
1 |
|
return $this->countsByNamespace; |
|
218
|
|
|
} |
|
219
|
|
|
|
|
220
|
1 |
|
$counts = []; |
|
221
|
|
|
|
|
222
|
1 |
|
foreach ($this->countPagesCreated() as $row) { |
|
223
|
1 |
|
$counts[$row['namespace']] = [ |
|
224
|
1 |
|
'count' => (int)$row['count'], |
|
225
|
1 |
|
'deleted' => (int)$row['deleted'], |
|
226
|
|
|
]; |
|
227
|
|
|
|
|
228
|
1 |
|
if (!in_array($this->redirects, ['noredirects', 'onlyredirects'])) { |
|
229
|
1 |
|
$counts[$row['namespace']]['redirects'] = (int)$row['redirects']; |
|
230
|
|
|
} |
|
231
|
|
|
} |
|
232
|
|
|
|
|
233
|
1 |
|
$this->countsByNamespace = $counts; |
|
234
|
1 |
|
return $this->countsByNamespace; |
|
235
|
|
|
} |
|
236
|
|
|
|
|
237
|
|
|
/** |
|
238
|
|
|
* Number of results to show, depending on the namespace. |
|
239
|
|
|
* @return int |
|
240
|
|
|
*/ |
|
241
|
1 |
|
public function resultsPerPage() |
|
242
|
|
|
{ |
|
243
|
1 |
|
if ($this->namespace === 'all') { |
|
244
|
|
|
return self::RESULTS_LIMIT_ALL_NAMESPACES; |
|
245
|
|
|
} |
|
246
|
1 |
|
return self::RESULTS_LIMIT_SINGLE_NAMESPACE; |
|
247
|
|
|
} |
|
248
|
|
|
|
|
249
|
|
|
/** |
|
250
|
|
|
* Whether or not the results include page assessments. |
|
251
|
|
|
* @return bool |
|
252
|
|
|
*/ |
|
253
|
1 |
|
public function hasPageAssessments() |
|
254
|
|
|
{ |
|
255
|
1 |
|
if ($this->hasPageAssessments === null) { |
|
256
|
1 |
|
$this->hasPageAssessments = $this->project->hasPageAssessments(); |
|
257
|
|
|
} |
|
258
|
1 |
|
return $this->hasPageAssessments; |
|
259
|
|
|
} |
|
260
|
|
|
|
|
261
|
|
|
/** |
|
262
|
|
|
* Run the query to get pages created by the user with options. |
|
263
|
|
|
* This is ran independently for each namespace if $this->namespace is 'all'. |
|
264
|
|
|
* @param string $namespace Namespace ID. |
|
265
|
|
|
* @return array |
|
266
|
|
|
*/ |
|
267
|
1 |
|
private function fetchPagesCreated($namespace) |
|
268
|
|
|
{ |
|
269
|
1 |
|
return $this->user->getRepository()->getPagesCreated( |
|
|
|
|
|
|
270
|
1 |
|
$this->project, |
|
271
|
1 |
|
$this->user, |
|
272
|
1 |
|
$namespace, |
|
273
|
1 |
|
$this->redirects, |
|
274
|
1 |
|
$this->resultsPerPage(), |
|
275
|
1 |
|
$this->offset * $this->resultsPerPage() |
|
276
|
|
|
); |
|
277
|
|
|
} |
|
278
|
|
|
|
|
279
|
|
|
/** |
|
280
|
|
|
* Run the query to get the number of pages created by the user |
|
281
|
|
|
* with given options. |
|
282
|
|
|
* @return array |
|
283
|
|
|
*/ |
|
284
|
1 |
|
private function countPagesCreated() |
|
285
|
|
|
{ |
|
286
|
1 |
|
return $this->user->getRepository()->countPagesCreated( |
|
|
|
|
|
|
287
|
1 |
|
$this->project, |
|
288
|
1 |
|
$this->user, |
|
289
|
1 |
|
$this->namespace, |
|
290
|
1 |
|
$this->redirects |
|
291
|
|
|
); |
|
292
|
|
|
} |
|
293
|
|
|
|
|
294
|
|
|
/** |
|
295
|
|
|
* Format the data, adding humanized timestamps, page titles, assessment badges, |
|
296
|
|
|
* and sorting by namespace and then timestamp. |
|
297
|
|
|
* @param array $pages As returned by self::fetchPagesCreated() |
|
298
|
|
|
* @return array |
|
299
|
|
|
*/ |
|
300
|
1 |
|
private function formatPages($pages) |
|
301
|
|
|
{ |
|
302
|
1 |
|
$results = []; |
|
303
|
|
|
|
|
304
|
1 |
|
foreach ($pages as $row) { |
|
305
|
|
|
// if (!isset($results[$row['namespace']])) { |
|
306
|
|
|
// $results[$row['namespace']] = []; |
|
307
|
|
|
// } |
|
308
|
|
|
|
|
309
|
1 |
|
$datetime = DateTime::createFromFormat('YmdHis', $row['rev_timestamp']); |
|
310
|
1 |
|
$datetimeKey = $datetime->format('YmdHi'); |
|
|
|
|
|
|
311
|
1 |
|
$datetimeHuman = $datetime->format('Y-m-d H:i'); |
|
312
|
|
|
|
|
313
|
1 |
|
$pageData = array_merge($row, [ |
|
314
|
1 |
|
'raw_time' => $row['rev_timestamp'], |
|
315
|
1 |
|
'human_time' => $datetimeHuman, |
|
316
|
1 |
|
'page_title' => str_replace('_', ' ', $row['page_title']) |
|
317
|
|
|
]); |
|
318
|
|
|
|
|
319
|
1 |
|
if ($this->hasPageAssessments()) { |
|
320
|
1 |
|
$pageData['badge'] = $this->project->getAssessmentBadgeURL($pageData['pa_class']); |
|
321
|
|
|
} |
|
322
|
|
|
|
|
323
|
1 |
|
$results[$row['namespace']][] = $pageData; |
|
324
|
|
|
} |
|
325
|
|
|
|
|
326
|
|
|
// ksort($results); |
|
327
|
|
|
|
|
328
|
|
|
// foreach (array_keys($results) as $key) { |
|
329
|
|
|
// krsort($results[$key]); |
|
330
|
|
|
// } |
|
331
|
|
|
|
|
332
|
1 |
|
return $results; |
|
333
|
|
|
} |
|
334
|
|
|
} |
|
335
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.