Passed
Push — master ( e6ce91...429907 )
by MusikAnimal
04:46
created

EditCounterController::rightsChangesAction()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 11
nc 2
nop 0
dl 0
loc 19
ccs 0
cts 0
cp 0
crap 6
rs 9.9
c 0
b 0
f 0
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\Component\DependencyInjection\ContainerInterface;
10
use Symfony\Component\HttpFoundation\JsonResponse;
11
use Symfony\Component\HttpFoundation\RedirectResponse;
12
use Symfony\Component\HttpFoundation\RequestStack;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
15
use Xtools\EditCounter;
16
use Xtools\EditCounterRepository;
17
use Xtools\ProjectRepository;
18
19
/**
20
 * Class EditCounterController
21
 */
22
class EditCounterController extends XtoolsController
23
{
24
    /** @var EditCounter The edit-counter, that does all the work. */
25
    protected $editCounter;
26
27
    /**
28
     * Get the name of the tool's index route. This is also the name of the associated model.
29
     * @return string
30
     * @codeCoverageIgnore
31
     */
32
    public function getIndexRoute()
33
    {
34
        return 'EditCounter';
35
    }
36
37
    /**
38
     * EditCounterController constructor.
39
     * @param RequestStack $requestStack
40
     * @param ContainerInterface $container
41
     */
42 1
    public function __construct(RequestStack $requestStack, ContainerInterface $container)
43
    {
44
        // Causes the tool to redirect to the Simple Edit Counter if the user has too high of an edit count.
45 1
        $this->tooHighEditCountAction = 'SimpleEditCounterResult';
46
47
        // The rightsChanges action is exempt from the edit count limitation.
48 1
        $this->tooHighEditCountActionBlacklist = ['rightsChanges'];
49
50 1
        parent::__construct($requestStack, $container);
51 1
    }
52
53
    /**
54
     * Every action in this controller (other than 'index') calls this first.
55
     * If a response is returned, the calling action is expected to return it.
56
     * @param string $key API key, as given in the request. Omit this for actions
57
     *   that are public (only /api/ec actions should pass this in).
58
     * @return RedirectResponse|null
59
     * @throws AccessDeniedException If attempting to access internal endpoint.
60
     * @codeCoverageIgnore
61
     */
62
    protected function setUpEditCounter($key = null)
63
    {
64
        // Return the EditCounter if we already have one.
65
        if ($this->editCounter instanceof EditCounter) {
0 ignored issues
show
introduced by
$this->editCounter is always a sub-type of Xtools\EditCounter. If $this->editCounter can have other possible types, add them to src/AppBundle/Controller/EditCounterController.php:24.
Loading history...
66
            return null;
67
        }
68
69
        // Validate key if attempted to make internal API request.
70
        if ($key && (string)$key !== (string)$this->container->getParameter('secret')) {
71
            throw $this->createAccessDeniedException('This endpoint is for internal use only.');
72
        }
73
74
        // Will redirect to Simple Edit Counter if they have too many edits, as defined self::construct.
75
        $this->validateUser($this->user->getUsername());
76
77
        // Instantiate EditCounter.
78
        $editCounterRepo = new EditCounterRepository();
79
        $editCounterRepo->setContainer($this->container);
80
        $this->editCounter = new EditCounter(
81
            $this->project,
82
            $this->user,
83
            $this->container->get('app.i18n_helper')
84
        );
85
        $this->editCounter->setRepository($editCounterRepo);
86
    }
87
88
    /**
89
     * The initial GET request that displays the search form.
90
     * @Route("/ec", name="EditCounter")
91
     * @Route("/ec/", name="EditCounterSlash")
92
     * @Route("/ec/index.php", name="EditCounterIndexPhp")
93
     * @Route("/ec/{project}", name="EditCounterProject")
94
     * @return RedirectResponse|Response
95
     */
96 1
    public function indexAction()
97
    {
98 1
        if (isset($this->params['project']) && isset($this->params['username'])) {
99
            return $this->redirectToRoute('EditCounterResult', $this->params);
100
        }
101
102
        // Otherwise fall through.
103 1
        return $this->render('editCounter/index.html.twig', [
104 1
            'xtPageTitle' => 'tool-editcounter',
105 1
            'xtSubtitle' => 'tool-editcounter-desc',
106 1
            'xtPage' => 'editcounter',
107 1
            'project' => $this->project,
108
        ]);
109
    }
110
111
    /**
112
     * Display all results.
113
     * @Route("/ec/{project}/{username}", name="EditCounterResult")
114
     * @return Response
115
     * @codeCoverageIgnore
116
     */
117
    public function resultAction()
118
    {
119
        $this->setUpEditCounter();
120
121
        $ret = [
122
            'xtTitle' => $this->user->getUsername() . ' - ' . $this->project->getTitle(),
123
            'xtPage' => 'editcounter',
124
            'user' => $this->user,
125
            'project' => $this->project,
126
            'ec' => $this->editCounter,
127
        ];
128
129
        // Used when querying for global rights changes.
130
        if ((bool)$this->container->hasParameter('app.is_labs')) {
131
            $ret['metaProject'] = ProjectRepository::getProject('metawiki', $this->container);
132
        }
133
134
        // Output the relevant format template.
135
        return $this->getFormattedResponse($this->request, 'editCounter/result', $ret);
136
    }
137
138
    /**
139
     * Display the general statistics section.
140
     * @Route("/ec-generalstats/{project}/{username}", name="EditCounterGeneralStats")
141
     * @return Response
142
     * @codeCoverageIgnore
143
     */
144
    public function generalStatsAction()
145
    {
146
        $this->setUpEditCounter();
147
148
        $ret = [
149
            'xtTitle' => $this->user->getUsername(),
150
            'xtPage' => 'editcounter',
151
            'is_sub_request' => $this->isSubRequest,
152
            'user' => $this->user,
153
            'project' => $this->project,
154
            'ec' => $this->editCounter,
155
        ];
156
157
        // Output the relevant format template.
158
        return $this->getFormattedResponse($this->request, 'editCounter/general_stats', $ret);
159
    }
160
161
    /**
162
     * Display the namespace totals section.
163
     * @Route("/ec-namespacetotals/{project}/{username}", name="EditCounterNamespaceTotals")
164
     * @return Response
165
     * @codeCoverageIgnore
166
     */
167
    public function namespaceTotalsAction()
168
    {
169
        $this->setUpEditCounter();
170
171
        $ret = [
172
            'xtTitle' => $this->user->getUsername(),
173
            'xtPage' => 'editcounter',
174
            'is_sub_request' => $this->isSubRequest,
175
            'user' => $this->user,
176
            'project' => $this->project,
177
            'ec' => $this->editCounter,
178
        ];
179
180
        // Output the relevant format template.
181
        return $this->getFormattedResponse($this->request, 'editCounter/namespace_totals', $ret);
182
    }
183
184
    /**
185
     * Display the timecard section.
186
     * @Route("/ec-timecard/{project}/{username}", name="EditCounterTimecard")
187
     * @return Response
188
     * @codeCoverageIgnore
189
     */
190
    public function timecardAction()
191
    {
192
        $this->setUpEditCounter();
193
194
        $optedInPage = $this->project
195
            ->getRepository()
196
            ->getPage($this->project, $this->project->userOptInPage($this->user));
197
198
        $ret = [
199
            'xtTitle' => $this->user->getUsername(),
200
            'xtPage' => 'editcounter',
201
            'is_sub_request' => $this->isSubRequest,
202
            'user' => $this->user,
203
            'project' => $this->project,
204
            'ec' => $this->editCounter,
205
            'opted_in_page' => $optedInPage,
206
        ];
207
208
        // Output the relevant format template.
209
        return $this->getFormattedResponse($this->request, 'editCounter/timecard', $ret);
210
    }
211
212
    /**
213
     * Display the year counts section.
214
     * @Route("/ec-yearcounts/{project}/{username}", name="EditCounterYearCounts")
215
     * @return Response
216
     * @codeCoverageIgnore
217
     */
218
    public function yearCountsAction()
219
    {
220
        $this->setUpEditCounter();
221
222
        $ret = [
223
            'xtTitle' => $this->user->getUsername(),
224
            'xtPage' => 'editcounter',
225
            'is_sub_request' => $this->isSubRequest,
226
            'user' => $this->user,
227
            'project' => $this->project,
228
            'ec' => $this->editCounter,
229
        ];
230
231
        // Output the relevant format template.
232
        return $this->getFormattedResponse($this->request, 'editCounter/yearcounts', $ret);
233
    }
234
235
    /**
236
     * Display the month counts section.
237
     * @Route("/ec-monthcounts/{project}/{username}", name="EditCounterMonthCounts")
238
     * @return Response
239
     * @codeCoverageIgnore
240
     */
241
    public function monthCountsAction()
242
    {
243
        $this->setUpEditCounter();
244
245
        $optedInPage = $this->project
246
            ->getRepository()
247
            ->getPage($this->project, $this->project->userOptInPage($this->user));
248
        $ret = [
249
            'xtTitle' => $this->user->getUsername(),
250
            'xtPage' => 'editcounter',
251
            'is_sub_request' => $this->isSubRequest,
252
            'user' => $this->user,
253
            'project' => $this->project,
254
            'ec' => $this->editCounter,
255
            'opted_in_page' => $optedInPage,
256
        ];
257
258
        // Output the relevant format template.
259
        return $this->getFormattedResponse($this->request, 'editCounter/monthcounts', $ret);
260
    }
261
262
    /**
263
     * Display the user rights changes section.
264
     * @Route("/ec-rightschanges/{project}/{username}", name="EditCounterRightsChanges")
265
     * @return Response
266
     * @codeCoverageIgnore
267
     */
268
    public function rightsChangesAction()
269
    {
270
        $this->setUpEditCounter();
271
272
        $ret = [
273
            'xtTitle' => $this->user->getUsername(),
274
            'xtPage' => 'editcounter',
275
            'is_sub_request' => $this->isSubRequest,
276
            'user' => $this->user,
277
            'project' => $this->project,
278
            'ec' => $this->editCounter,
279
        ];
280
281
        if ((bool)$this->container->hasParameter('app.is_labs')) {
282
            $ret['metaProject'] = ProjectRepository::getProject('metawiki', $this->container);
283
        }
284
285
        // Output the relevant format template.
286
        return $this->getFormattedResponse($this->request, 'editCounter/rights_changes', $ret);
287
    }
288
289
    /**
290
     * Display the latest global edits section.
291
     * @Route(
292
     *     "/ec-latestglobal-contributions/{project}/{username}/{offset}",
293
     *     name="EditCounterLatestGlobalContribs",
294
     *     requirements={"offset" = "|\d*"},
295
     *     defaults={"offset" = 0}
296
     * )
297
     * @Route(
298
     *     "/ec-latestglobal/{project}/{username}/{offset}",
299
     *     name="EditCounterLatestGlobal",
300
     *     requirements={"offset" = "|\d*"},
301
     *     defaults={"offset" = 0}
302
     * ),
303
     * @return Response
304
     * @codeCoverageIgnore
305
     */
306
    public function latestGlobalAction()
307
    {
308
        $this->setUpEditCounter();
309
310
        return $this->render('editCounter/latest_global.html.twig', [
311
            'xtTitle' => $this->user->getUsername(),
312
            'xtPage' => 'editcounter',
313
            'is_sub_request' => $this->isSubRequest,
314
            'user' => $this->user,
315
            'project' => $this->project,
316
            'ec' => $this->editCounter,
317
            'offset' => $this->request->get('offset'),
318
            'pageSize' => $this->request->get('pagesize'),
319
        ]);
320
    }
321
322
323
    /**
324
     * Below are internal API endpoints for the Edit Counter.
325
     * All only respond with JSON and only to requests passing in the value
326
     * of the 'secret' parameter. This should not be used in JavaScript or clientside
327
     * applications, rather only used internally.
328
     */
329
330
    /**
331
     * Get (most) of the general statistics as JSON.
332
     * @Route("/api/ec/pairdata/{project}/{username}/{key}", name="EditCounterApiPairData")
333
     * @param string $key API key.
334
     * @return JsonResponse|RedirectResponse
335
     * @codeCoverageIgnore
336
     */
337
    public function pairDataApiAction($key)
338
    {
339
        $this->setUpEditCounter($key);
340
341
        return new JsonResponse(
342
            $this->editCounter->getPairData(),
343
            Response::HTTP_OK
344
        );
345
    }
346
347
    /**
348
     * Get various log counts for the user as JSON.
349
     * @Route("/api/ec/logcounts/{project}/{username}/{key}", name="EditCounterApiLogCounts")
350
     * @param string $key API key.
351
     * @return JsonResponse|RedirectResponse
352
     * @codeCoverageIgnore
353
     */
354
    public function logCountsApiAction($key)
355
    {
356
        $this->setUpEditCounter($key);
357
358
        return new JsonResponse(
359
            $this->editCounter->getLogCounts(),
360
            Response::HTTP_OK
361
        );
362
    }
363
364
    /**
365
     * Get edit sizes for the user as JSON.
366
     * @Route("/api/ec/editsizes/{project}/{username}/{key}", name="EditCounterApiEditSizes")
367
     * @param string $key API key.
368
     * @return JsonResponse|RedirectResponse
369
     * @codeCoverageIgnore
370
     */
371
    public function editSizesApiAction($key)
372
    {
373
        $this->setUpEditCounter($key);
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}/{key}", name="EditCounterApiNamespaceTotals")
384
     * @param string $key API key.
385
     * @return Response|RedirectResponse
386
     * @codeCoverageIgnore
387
     */
388
    public function namespaceTotalsApiAction($key)
389
    {
390
        $this->setUpEditCounter($key);
391
392
        return new JsonResponse(
393
            $this->editCounter->namespaceTotals(),
394
            Response::HTTP_OK
395
        );
396
    }
397
398
    /**
399
     * Display or fetch the month counts for the user.
400
     * @Route("/api/ec/monthcounts/{project}/{username}/{key}", name="EditCounterApiMonthCounts")
401
     * @param string $key API key.
402
     * @return Response
403
     * @codeCoverageIgnore
404
     */
405
    public function monthCountsApiAction($key)
406
    {
407
        $this->setUpEditCounter($key);
408
409
        return new JsonResponse(
410
            $this->editCounter->monthCounts(),
411
            Response::HTTP_OK
412
        );
413
    }
414
}
415