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

TopEditsController::tooHighEditCountRoute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Controller;
6
7
use App\Helper\AutomatedEditsHelper;
8
use App\Helper\I18nHelper;
9
use App\Model\TopEdits;
10
use App\Repository\PageRepository;
11
use App\Repository\ProjectRepository;
12
use App\Repository\TopEditsRepository;
13
use App\Repository\UserRepository;
14
use GuzzleHttp\Client;
15
use Psr\Cache\CacheItemPoolInterface;
16
use Psr\Container\ContainerInterface;
17
use Symfony\Component\HttpFoundation\JsonResponse;
18
use Symfony\Component\HttpFoundation\RequestStack;
19
use Symfony\Component\HttpFoundation\Response;
20
use Symfony\Component\Routing\Annotation\Route;
21
22
/**
23
 * The Top Edits tool.
24
 */
25
class TopEditsController extends XtoolsController
26
{
27
    protected AutomatedEditsHelper $autoEditsHelper;
28
    protected TopEditsRepository $topEditsRepo;
29
30
    /**
31
     * @inheritDoc
32
     * @codeCoverageIgnore
33
     */
34
    public function getIndexRoute(): string
35
    {
36
        return 'TopEdits';
37
    }
38
39
    /**
40
     * TopEditsController constructor.
41
     * @param RequestStack $requestStack
42
     * @param ContainerInterface $container
43
     * @param CacheItemPoolInterface $cache
44
     * @param Client $guzzle
45
     * @param I18nHelper $i18n
46
     * @param ProjectRepository $projectRepo
47
     * @param UserRepository $userRepo
48
     * @param PageRepository $pageRepo
49
     * @param TopEditsRepository $topEditsRepo
50
     * @param AutomatedEditsHelper $autoEditsHelper
51
     */
52
    public function __construct(
53
        RequestStack $requestStack,
54
        ContainerInterface $container,
55
        CacheItemPoolInterface $cache,
56
        Client $guzzle,
57
        I18nHelper $i18n,
58
        ProjectRepository $projectRepo,
59
        UserRepository $userRepo,
60
        PageRepository $pageRepo,
61
        TopEditsRepository $topEditsRepo,
62
        AutomatedEditsHelper $autoEditsHelper
63
    ) {
64
        $this->topEditsRepo = $topEditsRepo;
65
        $this->autoEditsHelper = $autoEditsHelper;
66
        $this->limit = 1000;
67
        parent::__construct($requestStack, $container, $cache, $guzzle, $i18n, $projectRepo, $userRepo, $pageRepo);
68
    }
69
70
    /**
71
     * @inheritDoc
72
     * @codeCoverageIgnore
73
     */
74
    public function tooHighEditCountRoute(): string
75
    {
76
        return $this->getIndexRoute();
77
    }
78
79
    /**
80
     * The Top Edits by page action is exempt from the edit count limitation.
81
     * @inheritDoc
82
     * @codeCoverageIgnore
83
     */
84
    public function tooHighEditCountActionAllowlist(): array
85
    {
86
        return ['singlePageTopEdits'];
87
    }
88
89
    /**
90
     * @inheritDoc
91
     * @codeCoverageIgnore
92
     */
93
    public function restrictedApiActions(): array
94
    {
95
        return ['namespaceTopEditsUserApi'];
96
    }
97
98
    /**
99
     * Display the form.
100
     * @Route("/topedits", name="topedits")
101
     * @Route("/topedits", name="TopEdits")
102
     * @Route("/topedits/index.php", name="TopEditsIndex")
103
     * @Route("/topedits/{project}", name="TopEditsProject")
104
     * @return Response
105
     */
106
    public function indexAction(): Response
107
    {
108
        // Redirect if at minimum project and username are provided.
109
        if (isset($this->params['project']) && isset($this->params['username'])) {
110
            if (empty($this->params['page'])) {
111
                return $this->redirectToRoute('TopEditsResultNamespace', $this->params);
112
            }
113
            return $this->redirectToRoute('TopEditsResultPage', $this->params);
114
        }
115
116
        return $this->render('topedits/index.html.twig', array_merge([
117
            'xtPageTitle' => 'tool-topedits',
118
            'xtSubtitle' => 'tool-topedits-desc',
119
            'xtPage' => 'TopEdits',
120
121
            // Defaults that will get overriden if in $params.
122
            'namespace' => 0,
123
            'page' => '',
124
            'username' => '',
125
            'start' => '',
126
            'end' => '',
127
        ], $this->params, ['project' => $this->project]));
128
    }
129
130
    /**
131
     * Every action in this controller (other than 'index') calls this first.
132
     * @return TopEdits
133
     * @codeCoverageIgnore
134
     */
135
    public function setUpTopEdits(): TopEdits
136
    {
137
        return new TopEdits(
138
            $this->topEditsRepo,
139
            $this->autoEditsHelper,
140
            $this->project,
141
            $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\TopEdits::__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

141
            /** @scrutinizer ignore-type */ $this->user,
Loading history...
142
            $this->page,
143
            $this->namespace,
144
            $this->start,
145
            $this->end,
146
            $this->limit,
147
            (int)$this->request->query->get('pagination', 0)
148
        );
149
    }
150
151
    /**
152
     * List top edits by this user for all pages in a particular namespace.
153
     * @Route("/topedits/{project}/{username}/{namespace}/{start}/{end}",
154
     *     name="TopEditsResultNamespace",
155
     *     requirements={
156
     *         "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
157
     *         "namespace"="|all|\d+",
158
     *         "start"="|\d{4}-\d{2}-\d{2}",
159
     *         "end"="|\d{4}-\d{2}-\d{2}",
160
     *     },
161
     *     defaults={"namespace" = "all", "start"=false, "end"=false}
162
     * )
163
     * @return Response
164
     * @codeCoverageIgnore
165
     */
166
    public function namespaceTopEditsAction(): Response
167
    {
168
        // Max number of rows per namespace to show. `null` here will use the TopEdits default.
169
        $this->limit = $this->isSubRequest ? 10 : $this->limit;
170
171
        $topEdits = $this->setUpTopEdits();
172
        $topEdits->prepareData();
173
174
        $ret = [
175
            'xtPage' => 'TopEdits',
176
            '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

176
            '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...
177
            'te' => $topEdits,
178
            'is_sub_request' => $this->isSubRequest,
179
        ];
180
181
        // Output the relevant format template.
182
        return $this->getFormattedResponse('topedits/result_namespace', $ret);
183
    }
184
185
    /**
186
     * List top edits by this user for a particular page.
187
     * @Route("/topedits/{project}/{username}/{namespace}/{page}/{start}/{end}",
188
     *     name="TopEditsResultPage",
189
     *     requirements={
190
     *         "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
191
     *         "namespace"="|all|\d+",
192
     *         "page"="(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2})(?:\/(|\d{4}-\d{2}-\d{2}))?)?$",
193
     *         "start"="|\d{4}-\d{2}-\d{2}",
194
     *         "end"="|\d{4}-\d{2}-\d{2}",
195
     *     },
196
     *     defaults={"namespace"="all", "start"=false, "end"=false}
197
     * )
198
     * @todo Add pagination.
199
     * @return Response
200
     * @codeCoverageIgnore
201
     */
202
    public function singlePageTopEditsAction(): Response
203
    {
204
        $topEdits = $this->setUpTopEdits();
205
        $topEdits->prepareData();
206
207
        // Send all to the template.
208
        return $this->getFormattedResponse('topedits/result_article', [
209
            'xtPage' => 'TopEdits',
210
            'xtTitle' => $this->user->getUsername() . ' - ' . $this->page->getTitle(),
0 ignored issues
show
Bug introduced by
The method getTitle() 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

210
            'xtTitle' => $this->user->getUsername() . ' - ' . $this->page->/** @scrutinizer ignore-call */ getTitle(),

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...
211
            'te' => $topEdits,
212
        ]);
213
    }
214
215
    /************************ API endpoints ************************/
216
217
    /**
218
     * List top edits by this user for all pages in a particular namespace.
219
     * @Route("/api/user/top_edits/{project}/{username}/{namespace}/{start}/{end}",
220
     *     name="UserApiTopEditsNamespace",
221
     *     requirements={
222
     *         "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
223
     *         "namespace"="|\d+|all",
224
     *         "start"="|\d{4}-\d{2}-\d{2}",
225
     *         "end"="|\d{4}-\d{2}-\d{2}",
226
     *     },
227
     *     defaults={"namespace"="all", "start"=false, "end"=false}
228
     * )
229
     * @return JsonResponse
230
     * @codeCoverageIgnore
231
     */
232
    public function namespaceTopEditsUserApiAction(): JsonResponse
233
    {
234
        $this->recordApiUsage('user/topedits');
235
236
        $topEdits = $this->setUpTopEdits();
237
        $topEdits->prepareData();
238
239
        return $this->getFormattedApiResponse([
240
            'top_edits' => (object)$topEdits->getTopEdits(),
241
        ]);
242
    }
243
244
    /**
245
     * Get the all edits of a user to a specific page, maximum 1000.
246
     * @Route("/api/user/top_edits/{project}/{username}/{namespace}/{page}/{start}/{end}",
247
     *     name="UserApiTopEditsPage",
248
     *     requirements = {
249
     *         "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
250
     *         "namespace"="|\d+|all",
251
     *         "page"="(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2})(?:\/(|\d{4}-\d{2}-\d{2}))?)?$",
252
     *         "start"="|\d{4}-\d{2}-\d{2}",
253
     *         "end"="|\d{4}-\d{2}-\d{2}",
254
     *     },
255
     *     defaults={"namespace"="all", "start"=false, "end"=false}
256
     * )
257
     * @todo Add pagination.
258
     * @return JsonResponse
259
     * @codeCoverageIgnore
260
     */
261
    public function singlePageTopEditsUserApiAction(): JsonResponse
262
    {
263
        $this->recordApiUsage('user/topedits');
264
265
        $topEdits = $this->setUpTopEdits();
266
        $topEdits->prepareData(false);
267
268
        return $this->getFormattedApiResponse([
269
            'top_edits' => $topEdits->getTopEdits(),
270
        ]);
271
    }
272
}
273