|
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_PER_PAGE = 1000; |
|
18
|
|
|
|
|
19
|
|
|
/** @var Project The project. */ |
|
20
|
|
|
protected $project; |
|
21
|
|
|
|
|
22
|
|
|
/** @var User The user. */ |
|
23
|
|
|
protected $user; |
|
24
|
|
|
|
|
25
|
|
|
/** @var string Which namespace we are querying for. */ |
|
26
|
|
|
protected $namespace; |
|
27
|
|
|
|
|
28
|
|
|
/** @var string One of 'noredirects', 'onlyredirects' or blank for both. */ |
|
29
|
|
|
protected $redirects; |
|
30
|
|
|
|
|
31
|
|
|
/** @var int Pagination offset. */ |
|
32
|
|
|
protected $offset; |
|
33
|
|
|
|
|
34
|
|
|
/** @var array The list of pages including various statistics. */ |
|
35
|
|
|
protected $pages; |
|
36
|
|
|
|
|
37
|
|
|
/** @var array Number of redirects/pages that were created/deleted, broken down by namespace. */ |
|
38
|
|
|
protected $countsByNamespace; |
|
39
|
|
|
|
|
40
|
|
|
/** @var bool Whether or not the Project supports page assessments. */ |
|
41
|
|
|
protected $hasPageAssessments; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* Pages constructor. |
|
45
|
|
|
* @param Project $project |
|
46
|
|
|
* @param User $user |
|
47
|
|
|
* @param string|int $namespace Namespace ID or 'all'. |
|
48
|
|
|
* @param string $redirects One of 'noredirects', 'onlyredirects' or blank for both. |
|
49
|
|
|
* @param int $offset Pagination offset. |
|
50
|
|
|
*/ |
|
51
|
2 |
View Code Duplication |
public function __construct( |
|
|
|
|
|
|
52
|
|
|
Project $project, |
|
53
|
|
|
User $user, |
|
54
|
|
|
$namespace = 0, |
|
55
|
|
|
$redirects = 'noredirects', |
|
56
|
|
|
$offset = 0 |
|
57
|
|
|
) { |
|
58
|
2 |
|
$this->project = $project; |
|
59
|
2 |
|
$this->user = $user; |
|
60
|
2 |
|
$this->namespace = $namespace === 'all' ? 'all' : (string)$namespace; |
|
61
|
2 |
|
$this->redirects = $redirects; |
|
62
|
2 |
|
$this->offset = $offset; |
|
63
|
2 |
|
} |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* The project associated with this Pages instance. |
|
67
|
|
|
* @return Project |
|
68
|
|
|
*/ |
|
69
|
1 |
|
public function getProject() |
|
70
|
|
|
{ |
|
71
|
1 |
|
return $this->project; |
|
72
|
|
|
} |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* The user associated with this Pages instance. |
|
76
|
|
|
* @return User |
|
77
|
|
|
*/ |
|
78
|
1 |
|
public function getUser() |
|
79
|
|
|
{ |
|
80
|
1 |
|
return $this->user; |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
/** |
|
84
|
|
|
* The namespace associated with this Pages instance. |
|
85
|
|
|
* @return int|string |
|
86
|
|
|
*/ |
|
87
|
1 |
|
public function getNamespace() |
|
88
|
|
|
{ |
|
89
|
1 |
|
return $this->namespace; |
|
90
|
|
|
} |
|
91
|
|
|
|
|
92
|
|
|
/** |
|
93
|
|
|
* The redirects option associated with this Pages instance. |
|
94
|
|
|
* @return string |
|
95
|
|
|
*/ |
|
96
|
1 |
|
public function getRedirects() |
|
97
|
|
|
{ |
|
98
|
1 |
|
return $this->redirects; |
|
99
|
|
|
} |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* The pagination offset associated with this Pages instance. |
|
103
|
|
|
* @return int |
|
104
|
|
|
*/ |
|
105
|
1 |
|
public function getOffset() |
|
106
|
|
|
{ |
|
107
|
1 |
|
return $this->offset; |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
/** |
|
111
|
|
|
* Fetch and prepare the pages created by the user. |
|
112
|
|
|
* @codeCoverageIgnore |
|
113
|
|
|
*/ |
|
114
|
|
|
public function prepareData() |
|
115
|
|
|
{ |
|
116
|
|
|
$data = $this->fetchPagesCreated(); |
|
117
|
|
|
$this->pages = $this->formatPages($data); |
|
118
|
|
|
|
|
119
|
|
|
return $this->pages; |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* The public function to get the list of all pages created by the user, |
|
124
|
|
|
* (up to self::RESULTS_PER_PAGE), across all namespaces. |
|
125
|
|
|
* @return array |
|
126
|
|
|
*/ |
|
127
|
1 |
|
public function getResults() |
|
128
|
|
|
{ |
|
129
|
1 |
|
if ($this->pages === null) { |
|
130
|
|
|
$this->prepareData(); |
|
131
|
|
|
} |
|
132
|
1 |
|
return $this->pages; |
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
/** |
|
136
|
|
|
* Get the total number of pages we're showing data for. |
|
137
|
|
|
* @return int |
|
138
|
|
|
*/ |
|
139
|
1 |
|
public function getNumResults() |
|
140
|
|
|
{ |
|
141
|
1 |
|
$total = 0; |
|
142
|
1 |
|
foreach ($this->getCounts() as $ns => $values) { |
|
143
|
1 |
|
$total += $values['count']; |
|
144
|
|
|
} |
|
145
|
1 |
|
return $total; |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
/** |
|
149
|
|
|
* Get the total number of pages that are currently deleted. |
|
150
|
|
|
* @return int |
|
151
|
|
|
*/ |
|
152
|
1 |
|
public function getNumDeleted() |
|
153
|
|
|
{ |
|
154
|
1 |
|
$total = 0; |
|
155
|
1 |
|
foreach ($this->getCounts() as $ns => $values) { |
|
156
|
1 |
|
$total += $values['deleted']; |
|
157
|
|
|
} |
|
158
|
1 |
|
return $total; |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* Get the total number of pages that are currently redirects. |
|
163
|
|
|
* @return int |
|
164
|
|
|
*/ |
|
165
|
1 |
|
public function getNumRedirects() |
|
166
|
|
|
{ |
|
167
|
1 |
|
$total = 0; |
|
168
|
1 |
|
foreach ($this->getCounts() as $ns => $values) { |
|
169
|
1 |
|
$total += $values['redirects']; |
|
170
|
|
|
} |
|
171
|
1 |
|
return $total; |
|
172
|
|
|
} |
|
173
|
|
|
|
|
174
|
|
|
/** |
|
175
|
|
|
* Number of namespaces being reported. |
|
176
|
|
|
* @return int |
|
177
|
|
|
*/ |
|
178
|
|
|
public function getNumNamespaces() |
|
179
|
|
|
{ |
|
180
|
|
|
return count(array_keys($this->getCounts())); |
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
/** |
|
184
|
|
|
* Number of redirects/pages that were created/deleted, broken down by namespace. |
|
185
|
|
|
* @return array Namespace IDs as the keys, with values 'count', 'deleted' and 'redirects'. |
|
186
|
|
|
*/ |
|
187
|
1 |
|
public function getCounts() |
|
188
|
|
|
{ |
|
189
|
1 |
|
if ($this->countsByNamespace !== null) { |
|
190
|
1 |
|
return $this->countsByNamespace; |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
1 |
|
$counts = []; |
|
194
|
|
|
|
|
195
|
1 |
|
foreach ($this->countPagesCreated() as $row) { |
|
196
|
1 |
|
$counts[$row['namespace']] = [ |
|
197
|
1 |
|
'count' => $row['count'], |
|
198
|
1 |
|
'deleted' => $row['deleted'], |
|
199
|
1 |
|
'redirects' => $row['redirects'], |
|
200
|
|
|
]; |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
1 |
|
$this->countsByNamespace = $counts; |
|
204
|
1 |
|
return $this->countsByNamespace; |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
/** |
|
208
|
|
|
* Whether or not the results include page assessments. |
|
209
|
|
|
* @return bool |
|
210
|
|
|
*/ |
|
211
|
1 |
|
public function hasPageAssessments() |
|
212
|
|
|
{ |
|
213
|
1 |
|
if ($this->hasPageAssessments === null) { |
|
214
|
1 |
|
$this->hasPageAssessments = $this->project->hasPageAssessments(); |
|
215
|
|
|
} |
|
216
|
1 |
|
return $this->hasPageAssessments; |
|
217
|
|
|
} |
|
218
|
|
|
|
|
219
|
|
|
/** |
|
220
|
|
|
* Run the query to get pages created by the user with options. |
|
221
|
|
|
* @return array |
|
222
|
|
|
*/ |
|
223
|
1 |
|
private function fetchPagesCreated() |
|
224
|
|
|
{ |
|
225
|
1 |
|
return $this->user->getRepository()->getPagesCreated( |
|
|
|
|
|
|
226
|
1 |
|
$this->project, |
|
227
|
1 |
|
$this->user, |
|
228
|
1 |
|
$this->namespace, |
|
229
|
1 |
|
$this->redirects |
|
230
|
|
|
// $this->resultsPerPage(), |
|
231
|
|
|
// $this->offset * $this->resultsPerPage() |
|
232
|
|
|
); |
|
233
|
|
|
} |
|
234
|
|
|
|
|
235
|
|
|
/** |
|
236
|
|
|
* Number of results to show, depending on the namespace. |
|
237
|
|
|
* FIXME: This is a temporary measure. Ultimately we want UserRepository::getPagesCreated() |
|
238
|
|
|
* to apply the limit to each individual namespace it collects pages for. |
|
239
|
|
|
* @return int |
|
240
|
|
|
*/ |
|
241
|
|
|
private function resultsPerPage() |
|
|
|
|
|
|
242
|
|
|
{ |
|
243
|
|
|
if ($this->namespace === 'all') { |
|
244
|
|
|
return 0; |
|
245
|
|
|
} |
|
246
|
|
|
return self::RESULTS_PER_PAGE; |
|
247
|
|
|
} |
|
248
|
|
|
|
|
249
|
|
|
/** |
|
250
|
|
|
* Run the query to get the number of pages created by the user |
|
251
|
|
|
* with given options. |
|
252
|
|
|
* @return array |
|
253
|
|
|
*/ |
|
254
|
1 |
|
private function countPagesCreated() |
|
255
|
|
|
{ |
|
256
|
1 |
|
return $this->user->getRepository()->countPagesCreated( |
|
|
|
|
|
|
257
|
1 |
|
$this->project, |
|
258
|
1 |
|
$this->user, |
|
259
|
1 |
|
$this->namespace, |
|
260
|
1 |
|
$this->redirects |
|
261
|
|
|
); |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
/** |
|
265
|
|
|
* Format the data, adding humanized timestamps, page titles, assessment badges, |
|
266
|
|
|
* and sorting by namespace and then timestamp. |
|
267
|
|
|
* @param array $pages As returned by self::fetchPagesCreated() |
|
268
|
|
|
* @return array |
|
269
|
|
|
*/ |
|
270
|
1 |
|
private function formatPages($pages) |
|
271
|
|
|
{ |
|
272
|
1 |
|
$results = []; |
|
273
|
|
|
|
|
274
|
1 |
|
foreach ($pages as $row) { |
|
275
|
1 |
|
$datetime = DateTime::createFromFormat('YmdHis', $row['rev_timestamp']); |
|
276
|
1 |
|
$datetimeKey = $datetime->format('YmdHi'); |
|
277
|
1 |
|
$datetimeHuman = $datetime->format('Y-m-d H:i'); |
|
278
|
|
|
|
|
279
|
1 |
|
$pageData = array_merge($row, [ |
|
280
|
1 |
|
'raw_time' => $row['rev_timestamp'], |
|
281
|
1 |
|
'human_time' => $datetimeHuman, |
|
282
|
1 |
|
'page_title' => str_replace('_', ' ', $row['page_title']) |
|
283
|
|
|
]); |
|
284
|
|
|
|
|
285
|
1 |
|
if ($this->hasPageAssessments()) { |
|
286
|
1 |
|
$pageData['badge'] = $this->project->getAssessmentBadgeURL($pageData['pa_class']); |
|
287
|
|
|
} |
|
288
|
|
|
|
|
289
|
1 |
|
$results[$row['namespace']][$datetimeKey][] = $pageData; |
|
290
|
|
|
} |
|
291
|
|
|
|
|
292
|
1 |
|
ksort($results); |
|
293
|
|
|
|
|
294
|
1 |
|
foreach (array_keys($results) as $key) { |
|
295
|
1 |
|
krsort($results[$key]); |
|
296
|
|
|
} |
|
297
|
|
|
|
|
298
|
1 |
|
return $results; |
|
299
|
|
|
} |
|
300
|
|
|
} |
|
301
|
|
|
|
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.