|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* This file contains only the EditCounterController class. |
|
4
|
|
|
*/ |
|
5
|
|
|
|
|
6
|
|
|
namespace AppBundle\Controller; |
|
7
|
|
|
|
|
8
|
|
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; |
|
9
|
|
|
use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
|
10
|
|
|
use Symfony\Component\HttpFoundation\Request; |
|
11
|
|
|
use Symfony\Component\HttpFoundation\Response; |
|
12
|
|
|
use Symfony\Component\HttpFoundation\RedirectResponse; |
|
13
|
|
|
use Symfony\Component\HttpFoundation\JsonResponse; |
|
14
|
|
|
use Xtools\EditCounter; |
|
15
|
|
|
use Xtools\EditCounterRepository; |
|
16
|
|
|
use Xtools\Page; |
|
17
|
|
|
use Xtools\Project; |
|
18
|
|
|
use Xtools\ProjectRepository; |
|
19
|
|
|
use Xtools\User; |
|
20
|
|
|
use Xtools\UserRepository; |
|
21
|
|
|
|
|
22
|
|
|
/** |
|
23
|
|
|
* Class EditCounterController |
|
24
|
|
|
*/ |
|
25
|
|
|
class EditCounterController extends Controller |
|
26
|
|
|
{ |
|
27
|
|
|
|
|
28
|
|
|
/** @var User The user being queried. */ |
|
29
|
|
|
protected $user; |
|
30
|
|
|
|
|
31
|
|
|
/** @var Project The project being queried. */ |
|
32
|
|
|
protected $project; |
|
33
|
|
|
|
|
34
|
|
|
/** @var EditCounter The edit-counter, that does all the work. */ |
|
35
|
|
|
protected $editCounter; |
|
36
|
|
|
|
|
37
|
|
|
/** |
|
38
|
|
|
* Get the tool's shortname. |
|
39
|
|
|
* @return string |
|
40
|
|
|
*/ |
|
41
|
|
|
public function getToolShortname() |
|
42
|
|
|
{ |
|
43
|
|
|
return 'ec'; |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* Every action in this controller (other than 'index') calls this first. |
|
48
|
|
|
* If a response is returned, the calling action is expected to return it. |
|
49
|
|
|
* @param string|bool $project The project name. |
|
50
|
|
|
* @param string|bool $username The username. |
|
51
|
|
|
* @return null|RedirectResponse |
|
52
|
|
|
*/ |
|
53
|
|
|
protected function setUpEditCounter($project = false, $username = false) |
|
54
|
|
|
{ |
|
55
|
|
|
$this->project = ProjectRepository::getProject($project, $this->container); |
|
|
|
|
|
|
56
|
|
|
$this->user = UserRepository::getUser($username, $this->container); |
|
|
|
|
|
|
57
|
|
|
|
|
58
|
|
|
// Don't continue if the user doesn't exist. |
|
59
|
|
|
if (!$this->user->existsOnProject($this->project)) { |
|
60
|
|
|
$this->addFlash('notice', 'user-not-found'); |
|
61
|
|
|
return $this->redirectToRoute('ec', ['project' => $project]); |
|
62
|
|
|
} |
|
63
|
|
|
|
|
64
|
|
|
// Get an edit-counter if we don't already have it set. |
|
65
|
|
|
if ($this->editCounter instanceof EditCounter) { |
|
66
|
|
|
return; |
|
67
|
|
|
} |
|
68
|
|
|
$editCounterRepo = new EditCounterRepository(); |
|
69
|
|
|
$editCounterRepo->setContainer($this->container); |
|
|
|
|
|
|
70
|
|
|
$this->editCounter = new EditCounter($this->project, $this->user); |
|
71
|
|
|
$this->editCounter->setRepository($editCounterRepo); |
|
72
|
|
|
} |
|
73
|
|
|
|
|
74
|
|
|
/** |
|
75
|
|
|
* The initial GET request that displays the search form. |
|
76
|
|
|
* |
|
77
|
|
|
* @Route("/ec", name="ec") |
|
78
|
|
|
* @Route("/ec", name="EditCounter") |
|
79
|
|
|
* @Route("/ec/", name="EditCounterSlash") |
|
80
|
|
|
* @Route("/ec/index.php", name="EditCounterIndexPhp") |
|
81
|
|
|
* @Route("/ec/{project}", name="EditCounterProject") |
|
82
|
|
|
* |
|
83
|
|
|
* @param Request $request |
|
84
|
|
|
* @param string|null $project |
|
85
|
|
|
* @return RedirectResponse|Response |
|
86
|
|
|
*/ |
|
87
|
|
|
public function indexAction(Request $request, $project = null) |
|
88
|
|
|
{ |
|
89
|
|
|
$queryProject = $request->query->get('project'); |
|
90
|
|
|
$username = $request->query->get('username', $request->query->get('user')); |
|
91
|
|
|
|
|
92
|
|
|
if (($project || $queryProject) && $username) { |
|
|
|
|
|
|
93
|
|
|
$routeParams = ['project' => ($project ?: $queryProject), 'username' => $username]; |
|
94
|
|
|
return $this->redirectToRoute('EditCounterResult', $routeParams); |
|
95
|
|
|
} elseif (!$project && $queryProject) { |
|
|
|
|
|
|
96
|
|
|
return $this->redirectToRoute('EditCounterProject', ['project' => $queryProject]); |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
$project = ProjectRepository::getProject($project, $this->container); |
|
100
|
|
|
if (!$project->exists()) { |
|
101
|
|
|
$project = ProjectRepository::getDefaultProject($this->container); |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
// Otherwise fall through. |
|
105
|
|
|
return $this->render('editCounter/index.html.twig', [ |
|
106
|
|
|
'xtPageTitle' => 'tool-ec', |
|
107
|
|
|
'xtSubtitle' => 'tool-ec-desc', |
|
108
|
|
|
'xtPage' => 'ec', |
|
109
|
|
|
'project' => $project, |
|
110
|
|
|
]); |
|
111
|
|
|
} |
|
112
|
|
|
|
|
113
|
|
|
/** |
|
114
|
|
|
* Display all results. |
|
115
|
|
|
* @Route("/ec/{project}/{username}", name="EditCounterResult") |
|
116
|
|
|
* @param Request $request |
|
117
|
|
|
* @param string $project |
|
118
|
|
|
* @param string $username |
|
119
|
|
|
* @return Response |
|
120
|
|
|
*/ |
|
121
|
|
|
public function resultAction(Request $request, $project, $username) |
|
|
|
|
|
|
122
|
|
|
{ |
|
123
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
124
|
|
|
if ($ret instanceof RedirectResponse) { |
|
125
|
|
|
return $ret; |
|
126
|
|
|
} |
|
127
|
|
|
|
|
128
|
|
|
// Asynchronously collect some of the data that will be shown. |
|
129
|
|
|
// If multithreading is turned off, the normal getters in the views will |
|
130
|
|
|
// collect the necessary data synchronously. |
|
131
|
|
|
if ($this->container->getParameter('app.multithread')) { |
|
132
|
|
|
$this->editCounter->prepareData($this->container); |
|
|
|
|
|
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
// FIXME: is this needed? It shouldn't ever be a subrequest here in the resultAction. |
|
136
|
|
|
$isSubRequest = $this->container->get('request_stack')->getParentRequest() !== null; |
|
137
|
|
|
|
|
138
|
|
|
return $this->render('editCounter/result.html.twig', [ |
|
139
|
|
|
'xtTitle' => $this->user->getUsername() . ' - ' . $this->project->getTitle(), |
|
140
|
|
|
'xtPage' => 'ec', |
|
141
|
|
|
'base_dir' => realpath($this->getParameter('kernel.root_dir').'/..'), |
|
142
|
|
|
'is_sub_request' => $isSubRequest, |
|
143
|
|
|
'user' => $this->user, |
|
144
|
|
|
'project' => $this->project, |
|
145
|
|
|
'ec' => $this->editCounter, |
|
146
|
|
|
]); |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
/** |
|
150
|
|
|
* Display the general statistics section. |
|
151
|
|
|
* @Route("/ec-generalstats/{project}/{username}", name="EditCounterGeneralStats") |
|
152
|
|
|
* @param string $project |
|
153
|
|
|
* @param string $username |
|
154
|
|
|
* @return Response |
|
155
|
|
|
*/ |
|
156
|
|
View Code Duplication |
public function generalStatsAction($project, $username) |
|
|
|
|
|
|
157
|
|
|
{ |
|
158
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
159
|
|
|
if ($ret instanceof RedirectResponse) { |
|
160
|
|
|
return $ret; |
|
161
|
|
|
} |
|
162
|
|
|
|
|
163
|
|
|
$isSubRequest = $this->get('request_stack')->getParentRequest() !== null; |
|
164
|
|
|
return $this->render('editCounter/general_stats.html.twig', [ |
|
165
|
|
|
'xtTitle' => $this->user->getUsername(), |
|
166
|
|
|
'xtPage' => 'ec', |
|
167
|
|
|
'is_sub_request' => $isSubRequest, |
|
168
|
|
|
'user' => $this->user, |
|
169
|
|
|
'project' => $this->project, |
|
170
|
|
|
'ec' => $this->editCounter, |
|
171
|
|
|
]); |
|
172
|
|
|
} |
|
173
|
|
|
|
|
174
|
|
|
/** |
|
175
|
|
|
* Display the namespace totals section. |
|
176
|
|
|
* @Route("/ec-namespacetotals/{project}/{username}", name="EditCounterNamespaceTotals") |
|
177
|
|
|
* @param Request $request |
|
178
|
|
|
* @param string $project |
|
179
|
|
|
* @param string $username |
|
180
|
|
|
* @return Response |
|
181
|
|
|
*/ |
|
182
|
|
View Code Duplication |
public function namespaceTotalsAction(Request $request, $project, $username) |
|
|
|
|
|
|
183
|
|
|
{ |
|
184
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
185
|
|
|
if ($ret instanceof RedirectResponse) { |
|
186
|
|
|
return $ret; |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
|
|
$isSubRequest = $this->get('request_stack')->getParentRequest() !== null; |
|
190
|
|
|
return $this->render('editCounter/namespace_totals.html.twig', [ |
|
191
|
|
|
'xtTitle' => $this->user->getUsername(), |
|
192
|
|
|
'xtPage' => 'ec', |
|
193
|
|
|
'is_sub_request' => $isSubRequest, |
|
194
|
|
|
'user' => $this->user, |
|
195
|
|
|
'project' => $this->project, |
|
196
|
|
|
'ec' => $this->editCounter, |
|
197
|
|
|
]); |
|
198
|
|
|
} |
|
199
|
|
|
|
|
200
|
|
|
/** |
|
201
|
|
|
* Display the timecard section. |
|
202
|
|
|
* @Route("/ec-timecard/{project}/{username}", name="EditCounterTimecard") |
|
203
|
|
|
* @param string $project |
|
204
|
|
|
* @param string $username |
|
205
|
|
|
* @return Response |
|
206
|
|
|
*/ |
|
207
|
|
View Code Duplication |
public function timecardAction($project, $username) |
|
|
|
|
|
|
208
|
|
|
{ |
|
209
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
210
|
|
|
if ($ret instanceof RedirectResponse) { |
|
211
|
|
|
return $ret; |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
|
|
$isSubRequest = $this->get('request_stack')->getParentRequest() !== null; |
|
215
|
|
|
$optedInPage = $this->project |
|
|
|
|
|
|
216
|
|
|
->getRepository() |
|
217
|
|
|
->getPage($this->project, $this->project->userOptInPage($this->user)); |
|
218
|
|
|
return $this->render('editCounter/timecard.html.twig', [ |
|
219
|
|
|
'xtTitle' => $this->user->getUsername(), |
|
220
|
|
|
'xtPage' => 'ec', |
|
221
|
|
|
'is_sub_request' => $isSubRequest, |
|
222
|
|
|
'user' => $this->user, |
|
223
|
|
|
'project' => $this->project, |
|
224
|
|
|
'ec' => $this->editCounter, |
|
225
|
|
|
'opted_in_page' => $optedInPage, |
|
226
|
|
|
]); |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* Display the year counts section. |
|
231
|
|
|
* @Route("/ec-yearcounts/{project}/{username}", name="EditCounterYearCounts") |
|
232
|
|
|
* @param string $project |
|
233
|
|
|
* @param string $username |
|
234
|
|
|
* @return Response |
|
235
|
|
|
*/ |
|
236
|
|
View Code Duplication |
public function yearcountsAction($project, $username) |
|
|
|
|
|
|
237
|
|
|
{ |
|
238
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
239
|
|
|
if ($ret instanceof RedirectResponse) { |
|
240
|
|
|
return $ret; |
|
241
|
|
|
} |
|
242
|
|
|
|
|
243
|
|
|
$isSubRequest = $this->container->get('request_stack')->getParentRequest() !== null; |
|
244
|
|
|
return $this->render('editCounter/yearcounts.html.twig', [ |
|
245
|
|
|
'xtTitle' => $this->user->getUsername(), |
|
246
|
|
|
'xtPage' => 'ec', |
|
247
|
|
|
'is_sub_request' => $isSubRequest, |
|
248
|
|
|
'user' => $this->user, |
|
249
|
|
|
'project' => $this->project, |
|
250
|
|
|
'ec' => $this->editCounter, |
|
251
|
|
|
]); |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* Display the month counts section. |
|
256
|
|
|
* @Route("/ec-monthcounts/{project}/{username}", name="EditCounterMonthCounts") |
|
257
|
|
|
* @param Request $request |
|
258
|
|
|
* @param string $project |
|
259
|
|
|
* @param string $username |
|
260
|
|
|
* @return Response |
|
261
|
|
|
*/ |
|
262
|
|
View Code Duplication |
public function monthcountsAction(Request $request, $project, $username) |
|
|
|
|
|
|
263
|
|
|
{ |
|
264
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
265
|
|
|
if ($ret instanceof RedirectResponse) { |
|
266
|
|
|
return $ret; |
|
267
|
|
|
} |
|
268
|
|
|
|
|
269
|
|
|
$isSubRequest = $this->container->get('request_stack')->getParentRequest() !== null; |
|
270
|
|
|
$optedInPage = $this->project |
|
|
|
|
|
|
271
|
|
|
->getRepository() |
|
272
|
|
|
->getPage($this->project, $this->project->userOptInPage($this->user)); |
|
273
|
|
|
return $this->render('editCounter/monthcounts.html.twig', [ |
|
274
|
|
|
'xtTitle' => $this->user->getUsername(), |
|
275
|
|
|
'xtPage' => 'ec', |
|
276
|
|
|
'is_sub_request' => $isSubRequest, |
|
277
|
|
|
'user' => $this->user, |
|
278
|
|
|
'project' => $this->project, |
|
279
|
|
|
'ec' => $this->editCounter, |
|
280
|
|
|
'opted_in_page' => $optedInPage, |
|
281
|
|
|
]); |
|
282
|
|
|
} |
|
283
|
|
|
|
|
284
|
|
|
/** |
|
285
|
|
|
* Display the latest global edits section. |
|
286
|
|
|
* @Route("/ec-latestglobal/{project}/{username}", name="EditCounterLatestGlobal") |
|
287
|
|
|
* @param Request $request The HTTP request. |
|
288
|
|
|
* @param string $project The project name. |
|
289
|
|
|
* @param string $username The username. |
|
290
|
|
|
* @return Response |
|
291
|
|
|
*/ |
|
292
|
|
View Code Duplication |
public function latestglobalAction(Request $request, $project, $username) |
|
|
|
|
|
|
293
|
|
|
{ |
|
294
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
295
|
|
|
if ($ret instanceof RedirectResponse) { |
|
296
|
|
|
return $ret; |
|
297
|
|
|
} |
|
298
|
|
|
|
|
299
|
|
|
$isSubRequest = $request->get('htmlonly') |
|
300
|
|
|
|| $this->container->get('request_stack')->getParentRequest() !== null; |
|
301
|
|
|
return $this->render('editCounter/latest_global.html.twig', [ |
|
302
|
|
|
'xtTitle' => $this->user->getUsername(), |
|
303
|
|
|
'xtPage' => 'ec', |
|
304
|
|
|
'is_sub_request' => $isSubRequest, |
|
305
|
|
|
'user' => $this->user, |
|
306
|
|
|
'project' => $this->project, |
|
307
|
|
|
'ec' => $this->editCounter, |
|
308
|
|
|
]); |
|
309
|
|
|
} |
|
310
|
|
|
|
|
311
|
|
|
|
|
312
|
|
|
/** |
|
313
|
|
|
* Below are internal API endpoints for the Edit Counter. |
|
314
|
|
|
* All only respond with JSON and only to requests from the localhost |
|
315
|
|
|
* (see access_control in security.yml). |
|
316
|
|
|
*/ |
|
317
|
|
|
|
|
318
|
|
|
/** |
|
319
|
|
|
* Get (most) of the general statistics as JSON. |
|
320
|
|
|
* @Route("/api/ec/pairdata/{project}/{username}", name="EditCounterApiPairData") |
|
321
|
|
|
* @param Request $request |
|
322
|
|
|
* @param string $project |
|
323
|
|
|
* @param string $username |
|
324
|
|
|
* @return JsonResponse |
|
325
|
|
|
*/ |
|
326
|
|
View Code Duplication |
public function pairDataApiAction(Request $request, $project, $username) |
|
|
|
|
|
|
327
|
|
|
{ |
|
328
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
329
|
|
|
if ($ret instanceof RedirectResponse) { |
|
330
|
|
|
return $ret; |
|
|
|
|
|
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
return new JsonResponse( |
|
334
|
|
|
$this->editCounter->getPairData(), |
|
335
|
|
|
Response::HTTP_OK |
|
336
|
|
|
); |
|
337
|
|
|
} |
|
338
|
|
|
|
|
339
|
|
|
/** |
|
340
|
|
|
* Get various log counts for the user as JSON. |
|
341
|
|
|
* @Route("/api/ec/logcounts/{project}/{username}", name="EditCounterApiLogCounts") |
|
342
|
|
|
* @param Request $request |
|
343
|
|
|
* @param string $project |
|
344
|
|
|
* @param string $username |
|
345
|
|
|
* @return JsonResponse |
|
346
|
|
|
*/ |
|
347
|
|
View Code Duplication |
public function logCountsApiAction(Request $request, $project, $username) |
|
|
|
|
|
|
348
|
|
|
{ |
|
349
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
350
|
|
|
if ($ret instanceof RedirectResponse) { |
|
351
|
|
|
return $ret; |
|
|
|
|
|
|
352
|
|
|
} |
|
353
|
|
|
|
|
354
|
|
|
return new JsonResponse( |
|
355
|
|
|
$this->editCounter->getLogCounts(), |
|
356
|
|
|
Response::HTTP_OK |
|
357
|
|
|
); |
|
358
|
|
|
} |
|
359
|
|
|
|
|
360
|
|
|
/** |
|
361
|
|
|
* Get edit sizes for the user as JSON. |
|
362
|
|
|
* @Route("/api/ec/editsizes/{project}/{username}", name="EditCounterApiEditSizes") |
|
363
|
|
|
* @param Request $request |
|
364
|
|
|
* @param string $project |
|
365
|
|
|
* @param string $username |
|
366
|
|
|
* @return JsonResponse |
|
367
|
|
|
*/ |
|
368
|
|
View Code Duplication |
public function editSizesApiAction(Request $request, $project, $username) |
|
|
|
|
|
|
369
|
|
|
{ |
|
370
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
371
|
|
|
if ($ret instanceof RedirectResponse) { |
|
372
|
|
|
return $ret; |
|
|
|
|
|
|
373
|
|
|
} |
|
374
|
|
|
|
|
375
|
|
|
return new JsonResponse( |
|
376
|
|
|
$this->editCounter->getEditSizeData(), |
|
377
|
|
|
Response::HTTP_OK |
|
378
|
|
|
); |
|
379
|
|
|
} |
|
380
|
|
|
|
|
381
|
|
|
/** |
|
382
|
|
|
* Get the namespace totals for the user as JSON. |
|
383
|
|
|
* @Route("/api/ec/namespacetotals/{project}/{username}", name="EditCounterApiNamespaceTotals") |
|
384
|
|
|
* @param Request $request |
|
385
|
|
|
* @param string $project |
|
386
|
|
|
* @param string $username |
|
387
|
|
|
* @return Response |
|
388
|
|
|
*/ |
|
389
|
|
View Code Duplication |
public function namespaceTotalsApiAction(Request $request, $project, $username) |
|
|
|
|
|
|
390
|
|
|
{ |
|
391
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
392
|
|
|
if ($ret instanceof RedirectResponse) { |
|
393
|
|
|
return $ret; |
|
394
|
|
|
} |
|
395
|
|
|
|
|
396
|
|
|
return new JsonResponse( |
|
397
|
|
|
$this->editCounter->namespaceTotals(), |
|
398
|
|
|
Response::HTTP_OK |
|
399
|
|
|
); |
|
400
|
|
|
} |
|
401
|
|
|
|
|
402
|
|
|
/** |
|
403
|
|
|
* Display or fetch the month counts for the user. |
|
404
|
|
|
* @Route("/api/ec/monthcounts/{project}/{username}", name="EditCounterApiMonthCounts") |
|
405
|
|
|
* @param Request $request |
|
406
|
|
|
* @param string $project |
|
407
|
|
|
* @param string $username |
|
408
|
|
|
* @return Response |
|
409
|
|
|
*/ |
|
410
|
|
View Code Duplication |
public function monthcountsApiAction(Request $request, $project, $username) |
|
|
|
|
|
|
411
|
|
|
{ |
|
412
|
|
|
$ret = $this->setUpEditCounter($project, $username); |
|
413
|
|
|
if ($ret instanceof RedirectResponse) { |
|
414
|
|
|
return $ret; |
|
415
|
|
|
} |
|
416
|
|
|
|
|
417
|
|
|
return new JsonResponse( |
|
418
|
|
|
$this->editCounter->monthCounts(), |
|
419
|
|
|
Response::HTTP_OK |
|
420
|
|
|
); |
|
421
|
|
|
} |
|
422
|
|
|
} |
|
423
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.