Passed
Pull Request — main (#442)
by MusikAnimal
07:52 queued 03:55
created

singlePageTopEditsUserApiAction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 9
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
     * Get the name of the tool's index route. This is also the name of the associated model.
32
     * @return string
33
     * @codeCoverageIgnore
34
     */
35
    public function getIndexRoute(): string
36
    {
37
        return 'TopEdits';
38
    }
39
40
    /**
41
     * TopEditsController constructor.
42
     * @param RequestStack $requestStack
43
     * @param ContainerInterface $container
44
     * @param CacheItemPoolInterface $cache
45
     * @param Client $guzzle
46
     * @param I18nHelper $i18n
47
     * @param ProjectRepository $projectRepo
48
     * @param UserRepository $userRepo
49
     * @param PageRepository $pageRepo
50
     * @param TopEditsRepository $topEditsRepo
51
     * @param AutomatedEditsHelper $autoEditsHelper
52
     */
53
    public function __construct(
54
        RequestStack $requestStack,
55
        ContainerInterface $container,
56
        CacheItemPoolInterface $cache,
57
        Client $guzzle,
58
        I18nHelper $i18n,
59
        ProjectRepository $projectRepo,
60
        UserRepository $userRepo,
61
        PageRepository $pageRepo,
62
        TopEditsRepository $topEditsRepo,
63
        AutomatedEditsHelper $autoEditsHelper
64
    ) {
65
        $this->topEditsRepo = $topEditsRepo;
66
        $this->autoEditsHelper = $autoEditsHelper;
67
        $this->limit = 1000;
68
        parent::__construct($requestStack, $container, $cache, $guzzle, $i18n, $projectRepo, $userRepo, $pageRepo);
69
    }
70
71
    /**
72
     * @inheritDoc
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
     */
83
    public function tooHighEditCountActionAllowlist(): array
84
    {
85
        return ['singlePageTopEdits'];
86
    }
87
88
    /**
89
     * @inheritDoc
90
     */
91
    public function restrictedApiActions(): array
92
    {
93
        return ['namespaceTopEditsUserApi'];
94
    }
95
96
    /**
97
     * Display the form.
98
     * @Route("/topedits", name="topedits")
99
     * @Route("/topedits", name="TopEdits")
100
     * @Route("/topedits/index.php", name="TopEditsIndex")
101
     * @Route("/topedits/{project}", name="TopEditsProject")
102
     * @return Response
103
     */
104
    public function indexAction(): Response
105
    {
106
        // Redirect if at minimum project and username are provided.
107
        if (isset($this->params['project']) && isset($this->params['username'])) {
108
            if (empty($this->params['page'])) {
109
                return $this->redirectToRoute('TopEditsResultNamespace', $this->params);
110
            }
111
            return $this->redirectToRoute('TopEditsResultPage', $this->params);
112
        }
113
114
        return $this->render('topedits/index.html.twig', array_merge([
115
            'xtPageTitle' => 'tool-topedits',
116
            'xtSubtitle' => 'tool-topedits-desc',
117
            'xtPage' => 'TopEdits',
118
119
            // Defaults that will get overriden if in $params.
120
            'namespace' => 0,
121
            'page' => '',
122
            'username' => '',
123
            'start' => '',
124
            'end' => '',
125
        ], $this->params, ['project' => $this->project]));
126
    }
127
128
    /**
129
     * Every action in this controller (other than 'index') calls this first.
130
     * @return TopEdits
131
     * @codeCoverageIgnore
132
     */
133
    public function setUpTopEdits(): TopEdits
134
    {
135
        return new TopEdits(
136
            $this->topEditsRepo,
137
            $this->autoEditsHelper,
138
            $this->project,
139
            $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

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

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

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