Passed
Push — main ( 49d96d...eb753e )
by MusikAnimal
04:04
created

AutomatedEditsController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 10
dl 0
loc 16
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Controller;
6
7
use App\Model\AutoEdits;
8
use App\Repository\AutoEditsRepository;
9
use App\Repository\EditRepository;
10
use Symfony\Component\HttpFoundation\JsonResponse;
11
use Symfony\Component\HttpFoundation\RedirectResponse;
12
use Symfony\Component\HttpFoundation\Response;
13
use Symfony\Component\Routing\Annotation\Route;
14
15
/**
16
 * This controller serves the AutomatedEdits tool.
17
 */
18
class AutomatedEditsController extends XtoolsController
19
{
20
    protected AutoEdits $autoEdits;
21
22
    /** @var array Data that is passed to the view. */
23
    private array $output;
24
25
    /**
26
     * @inheritDoc
27
     * @codeCoverageIgnore
28
     */
29
    public function getIndexRoute(): string
30
    {
31
        return 'AutoEdits';
32
    }
33
34
    /**
35
     * This causes the tool to redirect back to the index page, with an error,
36
     * if the user has too high of an edit count.
37
     * @inheritDoc
38
     * @codeCoverageIgnore
39
     */
40
    public function tooHighEditCountRoute(): string
41
    {
42
        return $this->getIndexRoute();
43
    }
44
45
    /**
46
     * Display the search form.
47
     * @Route("/autoedits", name="AutoEdits")
48
     * @Route("/automatededits", name="AutoEditsLong")
49
     * @Route("/autoedits/index.php", name="AutoEditsIndexPhp")
50
     * @Route("/automatededits/index.php", name="AutoEditsLongIndexPhp")
51
     * @Route("/autoedits/{project}", name="AutoEditsProject")
52
     * @return Response
53
     */
54
    public function indexAction(): Response
55
    {
56
        // Redirect if at minimum project and username are provided.
57
        if (isset($this->params['project']) && isset($this->params['username'])) {
58
            // If 'tool' param is given, redirect to corresponding action.
59
            $tool = $this->request->query->get('tool');
60
61
            if ('all' === $tool) {
62
                unset($this->params['tool']);
63
                return $this->redirectToRoute('AutoEditsContributionsResult', $this->params);
64
            } elseif ('' != $tool && 'none' !== $tool) {
65
                $this->params['tool'] = $tool;
66
                return $this->redirectToRoute('AutoEditsContributionsResult', $this->params);
67
            } elseif ('none' === $tool) {
68
                unset($this->params['tool']);
69
            }
70
71
            // Otherwise redirect to the normal result action.
72
            return $this->redirectToRoute('AutoEditsResult', $this->params);
73
        }
74
75
        return $this->render('autoEdits/index.html.twig', array_merge([
76
            'xtPageTitle' => 'tool-autoedits',
77
            'xtSubtitle' => 'tool-autoedits-desc',
78
            'xtPage' => 'AutoEdits',
79
80
            // Defaults that will get overridden if in $this->params.
81
            'username' => '',
82
            'namespace' => 0,
83
            'start' => '',
84
            'end' => '',
85
        ], $this->params, ['project' => $this->project]));
86
    }
87
88
    /**
89
     * Set defaults, and instantiate the AutoEdits model. This is called at the top of every view action.
90
     * @param AutoEditsRepository $autoEditsRepo
91
     * @param EditRepository $editRepo
92
     * @codeCoverageIgnore
93
     */
94
    private function setupAutoEdits(AutoEditsRepository $autoEditsRepo, EditRepository $editRepo): void
95
    {
96
        $tool = $this->request->query->get('tool', null);
97
        $useSandbox = (bool)$this->request->query->get('usesandbox', false);
98
99
        if ($useSandbox && !$this->request->getSession()->get('logged_in_user')) {
100
            $this->addFlashMessage('danger', 'auto-edits-logged-out');
101
            $useSandbox = false;
102
        }
103
        $autoEditsRepo->setUseSandbox($useSandbox);
104
105
        $misconfigured = $autoEditsRepo->getInvalidTools($this->project);
106
        $helpLink = "https://w.wiki/ppr";
107
        foreach ($misconfigured as $tool) {
108
            $this->addFlashMessage('warning', 'auto-edits-misconfiguration', [$tool, $helpLink]);
109
        }
110
111
        // Validate tool.
112
        // FIXME: instead of redirecting to index page, show result page listing all tools for that project,
113
        //  clickable to show edits by the user, etc.
114
        if ($tool && !isset($autoEditsRepo->getTools($this->project)[$tool])) {
115
            $this->throwXtoolsException(
116
                $this->getIndexRoute(),
117
                'auto-edits-unknown-tool',
118
                [$tool],
119
                'tool'
120
            );
121
        }
122
123
        $this->autoEdits = new AutoEdits(
124
            $autoEditsRepo,
125
            $editRepo,
126
            $this->pageRepo,
127
            $this->userRepo,
128
            $this->project,
129
            $this->user,
0 ignored issues
show
Bug introduced by
It seems like $this->user can also be of type null; however, parameter $user of App\Model\AutoEdits::__construct() does only seem to accept App\Model\User, maybe add an additional type check? ( Ignorable by Annotation )

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

129
            /** @scrutinizer ignore-type */ $this->user,
Loading history...
130
            $this->namespace,
131
            $this->start,
132
            $this->end,
133
            $tool,
134
            $this->offset,
135
            $this->limit
136
        );
137
138
        $this->output = [
139
            'xtPage' => 'AutoEdits',
140
            'xtTitle' => $this->user->getUsername(),
0 ignored issues
show
Bug introduced by
The method getUsername() does not exist on null. ( Ignorable by Annotation )

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

140
            'xtTitle' => $this->user->/** @scrutinizer ignore-call */ getUsername(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
141
            'ae' => $this->autoEdits,
142
            'is_sub_request' => $this->isSubRequest,
143
        ];
144
    }
145
146
    /**
147
     * Display the results.
148
     * @Route(
149
     *     "/autoedits/{project}/{username}/{namespace}/{start}/{end}/{offset}", name="AutoEditsResult",
150
     *     requirements={
151
     *         "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
152
     *         "namespace"="|all|\d+",
153
     *         "start"="|\d{4}-\d{2}-\d{2}",
154
     *         "end"="|\d{4}-\d{2}-\d{2}",
155
     *         "offset"="|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}",
156
     *     },
157
     *     defaults={"namespace"=0, "start"=false, "end"=false, "offset"=false}
158
     * )
159
     * @param AutoEditsRepository $autoEditsRepo
160
     * @param EditRepository $editRepo
161
     * @return Response
162
     * @codeCoverageIgnore
163
     */
164
    public function resultAction(AutoEditsRepository $autoEditsRepo, EditRepository $editRepo): Response
165
    {
166
        // Will redirect back to index if the user has too high of an edit count.
167
        $this->setupAutoEdits($autoEditsRepo, $editRepo);
168
169
        if (in_array('bot', $this->user->getUserRights($this->project))) {
170
            $this->addFlashMessage('warning', 'auto-edits-bot');
171
        }
172
173
        return $this->getFormattedResponse('autoEdits/result', $this->output);
174
    }
175
176
    /**
177
     * Get non-automated edits for the given user.
178
     * @Route(
179
     *   "/nonautoedits-contributions/{project}/{username}/{namespace}/{start}/{end}/{offset}",
180
     *   name="NonAutoEditsContributionsResult",
181
     *   requirements={
182
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
183
     *       "namespace"="|all|\d+",
184
     *       "start"="|\d{4}-\d{2}-\d{2}",
185
     *       "end"="|\d{4}-\d{2}-\d{2}",
186
     *       "offset"="|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}",
187
     *   },
188
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=false}
189
     * )
190
     * @param AutoEditsRepository $autoEditsRepo
191
     * @param EditRepository $editRepo
192
     * @return Response|RedirectResponse
193
     * @codeCoverageIgnore
194
     */
195
    public function nonAutomatedEditsAction(AutoEditsRepository $autoEditsRepo, EditRepository $editRepo): Response
196
    {
197
        $this->setupAutoEdits($autoEditsRepo, $editRepo);
198
        return $this->getFormattedResponse('autoEdits/nonautomated_edits', $this->output);
199
    }
200
201
    /**
202
     * Get automated edits for the given user using the given tool.
203
     * @Route(
204
     *   "/autoedits-contributions/{project}/{username}/{namespace}/{start}/{end}/{offset}",
205
     *   name="AutoEditsContributionsResult",
206
     *   requirements={
207
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
208
     *       "namespace"="|all|\d+",
209
     *       "start"="|\d{4}-\d{2}-\d{2}",
210
     *       "end"="|\d{4}-\d{2}-\d{2}",
211
     *       "offset"="|\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}",
212
     *   },
213
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=false}
214
     * )
215
     * @param AutoEditsRepository $autoEditsRepo
216
     * @param EditRepository $editRepo
217
     * @return Response
218
     * @codeCoverageIgnore
219
     */
220
    public function automatedEditsAction(AutoEditsRepository $autoEditsRepo, EditRepository $editRepo): Response
221
    {
222
        $this->setupAutoEdits($autoEditsRepo, $editRepo);
223
224
        return $this->getFormattedResponse('autoEdits/automated_edits', $this->output);
225
    }
226
227
    /************************ API endpoints ************************/
228
229
    /**
230
     * Get a list of the automated tools and their regex/tags/etc.
231
     * @Route("/api/user/automated_tools/{project}", name="UserApiAutoEditsTools")
232
     * @Route("/api/project/automated_tools/{project}", name="ProjectApiAutoEditsTools")
233
     * @param AutoEditsRepository $autoEditsRepo
234
     * @return JsonResponse
235
     * @codeCoverageIgnore
236
     */
237
    public function automatedToolsApiAction(AutoEditsRepository $autoEditsRepo): JsonResponse
238
    {
239
        $this->recordApiUsage('user/automated_tools');
240
        return $this->getFormattedApiResponse($autoEditsRepo->getTools($this->project));
241
    }
242
243
    /**
244
     * Count the number of automated edits the given user has made.
245
     * @Route(
246
     *   "/api/user/automated_editcount/{project}/{username}/{namespace}/{start}/{end}/{tools}",
247
     *   name="UserApiAutoEditsCount",
248
     *   requirements={
249
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
250
     *       "namespace"="|all|\d+",
251
     *       "start"="|\d{4}-\d{2}-\d{2}",
252
     *       "end"="|\d{4}-\d{2}-\d{2}"
253
     *   },
254
     *   defaults={"namespace"="all", "start"=false, "end"=false, "tools"=false}
255
     * )
256
     * @param AutoEditsRepository $autoEditsRepo
257
     * @param EditRepository $editRepo
258
     * @return JsonResponse
259
     * @codeCoverageIgnore
260
     */
261
    public function automatedEditCountApiAction(
262
        AutoEditsRepository $autoEditsRepo,
263
        EditRepository $editRepo
264
    ): JsonResponse {
265
        $this->recordApiUsage('user/automated_editcount');
266
267
        $this->setupAutoEdits($autoEditsRepo, $editRepo);
268
269
        $ret = [
270
            'total_editcount' => $this->autoEdits->getEditCount(),
271
            'automated_editcount' => $this->autoEdits->getAutomatedCount(),
272
        ];
273
        $ret['nonautomated_editcount'] = $ret['total_editcount'] - $ret['automated_editcount'];
274
275
        if (isset($this->params['tools'])) {
276
            $tools = $this->autoEdits->getToolCounts();
277
            $ret['automated_tools'] = $tools;
278
        }
279
280
        return $this->getFormattedApiResponse($ret);
281
    }
282
283
    /**
284
     * Get non-automated edits for the given user.
285
     * @Route(
286
     *   "/api/user/nonautomated_edits/{project}/{username}/{namespace}/{start}/{end}/{offset}",
287
     *   name="UserApiNonAutoEdits",
288
     *   requirements={
289
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
290
     *       "namespace"="|all|\d+",
291
     *       "start"="|\d{4}-\d{2}-\d{2}",
292
     *       "end"="|\d{4}-\d{2}-\d{2}",
293
     *       "offset"="|\d{4}-?\d{2}-?\d{2}T?\d{2}:?\d{2}:?\d{2}"
294
     *   },
295
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=false, "limit"=50}
296
     * )
297
     * @param AutoEditsRepository $autoEditsRepo
298
     * @param EditRepository $editRepo
299
     * @return JsonResponse
300
     * @codeCoverageIgnore
301
     */
302
    public function nonAutomatedEditsApiAction(
303
        AutoEditsRepository $autoEditsRepo,
304
        EditRepository $editRepo
305
    ): JsonResponse {
306
        $this->recordApiUsage('user/nonautomated_edits');
307
308
        $this->setupAutoEdits($autoEditsRepo, $editRepo);
309
310
        $out = $this->addFullPageTitlesAndContinue(
311
            'nonautomated_edits',
312
            [],
313
            $this->autoEdits->getNonAutomatedEdits(true)
314
        );
315
316
        return $this->getFormattedApiResponse($out);
317
    }
318
319
    /**
320
     * Get (semi-)automated edits for the given user, optionally using the given tool.
321
     * @Route(
322
     *   "/api/user/automated_edits/{project}/{username}/{namespace}/{start}/{end}/{offset}",
323
     *   name="UserApiAutoEdits",
324
     *   requirements={
325
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
326
     *       "namespace"="|all|\d+",
327
     *       "start"="|\d{4}-\d{2}-\d{2}",
328
     *       "end"="|\d{4}-\d{2}-\d{2}",
329
     *       "offset"="|\d{4}-?\d{2}-?\d{2}T?\d{2}:?\d{2}:?\d{2}",
330
     *   },
331
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=false, "limit"=50}
332
     * )
333
     * @param AutoEditsRepository $autoEditsRepo
334
     * @param EditRepository $editRepo
335
     * @return Response
336
     * @codeCoverageIgnore
337
     */
338
    public function automatedEditsApiAction(AutoEditsRepository $autoEditsRepo, EditRepository $editRepo): Response
339
    {
340
        $this->recordApiUsage('user/automated_edits');
341
342
        $this->setupAutoEdits($autoEditsRepo, $editRepo);
343
344
        $extras = $this->autoEdits->getTool()
345
            ? ['tool' => $this->autoEdits->getTool()]
346
            : [];
347
348
        $out = $this->addFullPageTitlesAndContinue(
349
            'automated_edits',
350
            $extras,
351
            $this->autoEdits->getAutomatedEdits(true)
352
        );
353
354
        return $this->getFormattedApiResponse($out);
355
    }
356
}
357