Test Failed
Push — dependency-injection ( 7565fa )
by MusikAnimal
07:05
created

CategoryEditsController::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\Exception\XtoolsHttpException;
8
use App\Helper\I18nHelper;
9
use App\Model\CategoryEdits;
10
use App\Repository\CategoryEditsRepository;
11
use App\Repository\EditRepository;
12
use App\Repository\PageRepository;
13
use App\Repository\ProjectRepository;
14
use App\Repository\UserRepository;
15
use GuzzleHttp\Client;
16
use Psr\Cache\CacheItemPoolInterface;
17
use Psr\Container\ContainerInterface;
18
use Symfony\Component\HttpFoundation\JsonResponse;
19
use Symfony\Component\HttpFoundation\RequestStack;
20
use Symfony\Component\HttpFoundation\Response;
21
use Symfony\Component\Routing\Annotation\Route;
22
23
/**
24
 * This controller serves the Category Edits tool.
25
 */
26
class CategoryEditsController extends XtoolsController
27
{
28
    protected CategoryEdits $categoryEdits;
29
    protected CategoryEditsRepository $categoryEditsRepo;
30
    protected EditRepository $editRepo;
31
32
    /** @var string[] The categories, with or without namespace. */
33
    protected array $categories;
34
35
    /** @var array Data that is passed to the view. */
36
    private array $output;
37
38
    /**
39
     * Get the name of the tool's index route.
40
     * This is also the name of the associated model.
41
     * @return string
42
     * @codeCoverageIgnore
43
     */
44
    public function getIndexRoute(): string
45
    {
46
        return 'CategoryEdits';
47
    }
48
49
    /**
50
     * @param RequestStack $requestStack
51
     * @param ContainerInterface $container
52
     * @param CacheItemPoolInterface $cache
53
     * @param Client $guzzle
54
     * @param I18nHelper $i18n
55
     * @param ProjectRepository $projectRepo
56
     * @param UserRepository $userRepo
57
     * @param PageRepository $pageRepo
58
     * @param EditRepository $editRepo
59
     * @param CategoryEditsRepository $categoryEditsRepo
60
     */
61
    public function __construct(
62
        RequestStack $requestStack,
63
        ContainerInterface $container,
64
        CacheItemPoolInterface $cache,
65
        Client $guzzle,
66
        I18nHelper $i18n,
67
        ProjectRepository $projectRepo,
68
        UserRepository $userRepo,
69
        PageRepository $pageRepo,
70
        EditRepository $editRepo,
71
        CategoryEditsRepository $categoryEditsRepo
72
    ) {
73
        $this->editRepo = $editRepo;
74
        $this->pageRepo = $pageRepo;
75
        $this->categoryEditsRepo = $categoryEditsRepo;
76
        parent::__construct($requestStack, $container, $cache, $guzzle, $i18n, $projectRepo, $userRepo, $pageRepo);
77
    }
78
79
    /**
80
     * Will redirect back to index if the user has too high of an edit count.
81
     * @return string
82
     */
83
    public function tooHighEditCountRoute(): string
84
    {
85
        return $this->getIndexRoute();
86
    }
87
88
    /**
89
     * Display the search form.
90
     * @Route("/categoryedits", name="CategoryEdits")
91
     * @Route("/categoryedits/{project}", name="CategoryEditsProject")
92
     * @return Response
93
     * @codeCoverageIgnore
94
     */
95
    public function indexAction(): Response
96
    {
97
        // Redirect if at minimum project, username and categories are provided.
98
        if (isset($this->params['project']) && isset($this->params['username']) && isset($this->params['categories'])) {
99
            return $this->redirectToRoute('CategoryEditsResult', $this->params);
100
        }
101
102
        return $this->render('categoryEdits/index.html.twig', array_merge([
103
            'xtPageTitle' => 'tool-categoryedits',
104
            'xtSubtitle' => 'tool-categoryedits-desc',
105
            'xtPage' => 'CategoryEdits',
106
107
            // Defaults that will get overridden if in $params.
108
            'namespace' => 0,
109
            'start' => '',
110
            'end' => '',
111
            'username' => '',
112
            'categories' => '',
113
        ], $this->params, ['project' => $this->project]));
114
    }
115
116
    /**
117
     * Set defaults, and instantiate the CategoryEdits model. This is called at the top of every view action.
118
     * @codeCoverageIgnore
119
     */
120
    private function setupCategoryEdits(): void
121
    {
122
        $this->extractCategories();
123
124
        $this->categoryEdits = new CategoryEdits(
125
            $this->categoryEditsRepo,
126
            $this->editRepo,
127
            $this->pageRepo,
128
            $this->userRepo,
129
            $this->project,
130
            $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\CategoryEdits::__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

130
            /** @scrutinizer ignore-type */ $this->user,
Loading history...
131
            $this->categories,
132
            $this->start,
133
            $this->end,
134
            $this->offset
135
        );
136
137
        $this->output = [
138
            'xtPage' => 'CategoryEdits',
139
            '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

139
            '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...
140
            'project' => $this->project,
141
            'user' => $this->user,
142
            'ce' => $this->categoryEdits,
143
            'is_sub_request' => $this->isSubRequest,
144
        ];
145
    }
146
147
    /**
148
     * Go through the categories and normalize values, and set them on class properties.
149
     * @codeCoverageIgnore
150
     */
151
    private function extractCategories(): void
152
    {
153
        // Split categories by pipe.
154
        $categories = explode('|', $this->request->get('categories'));
0 ignored issues
show
Bug introduced by
It seems like $this->request->get('categories') can also be of type null; however, parameter $string of explode() does only seem to accept string, 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

154
        $categories = explode('|', /** @scrutinizer ignore-type */ $this->request->get('categories'));
Loading history...
155
156
        // Loop through the given categories, stripping out the namespace.
157
        // If a namespace was removed, it is flagged it as normalize
158
        // We look for the wiki's category namespace name, and the MediaWiki default
159
        // 'Category:', which sometimes is used cross-wiki (because it still works).
160
        $normalized = false;
161
        $nsName = $this->project->getNamespaces()[14].':';
162
        $this->categories = array_map(function ($category) use ($nsName, &$normalized) {
163
            if (0 === strpos($category, $nsName) || 0 === strpos($category, 'Category:')) {
164
                $normalized = true;
165
            }
166
            return preg_replace('/^'.$nsName.'/', '', $category);
167
        }, $categories);
168
169
        // Redirect if normalized, since we don't want the Category: prefix in the URL.
170
        if ($normalized) {
171
            throw new XtoolsHttpException(
172
                '',
173
                $this->generateUrl($this->request->get('_route'), array_merge(
0 ignored issues
show
Bug introduced by
It seems like $this->request->get('_route') can also be of type null; however, parameter $route of Symfony\Bundle\Framework...ntroller::generateUrl() does only seem to accept string, 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

173
                $this->generateUrl(/** @scrutinizer ignore-type */ $this->request->get('_route'), array_merge(
Loading history...
174
                    $this->request->attributes->get('_route_params'),
175
                    ['categories' => implode('|', $this->categories)]
176
                ))
177
            );
178
        }
179
    }
180
181
    /**
182
     * Display the results.
183
     * @Route(
184
     *     "/categoryedits/{project}/{username}/{categories}/{start}/{end}/{offset}",
185
     *     name="CategoryEditsResult",
186
     *     requirements={
187
     *         "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
188
     *         "categories"="(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2})(?:\/(|\d{4}-\d{2}-\d{2}))?)?$",
189
     *         "start"="|\d{4}-\d{2}-\d{2}",
190
     *         "end"="|\d{4}-\d{2}-\d{2}",
191
     *         "offset"="|\d{4}-?\d{2}-?\d{2}T?\d{2}:?\d{2}:?\d{2}",
192
     *     },
193
     *     defaults={"start"=false, "end"=false, "offset"=false}
194
     * )
195
     * @param CategoryEditsRepository $categoryEditsRepo
196
     * @return Response
197
     * @codeCoverageIgnore
198
     */
199
    public function resultAction(CategoryEditsRepository $categoryEditsRepo): Response
200
    {
201
        $this->setupCategoryEdits($categoryEditsRepo);
0 ignored issues
show
Unused Code introduced by
The call to App\Controller\CategoryE...r::setupCategoryEdits() has too many arguments starting with $categoryEditsRepo. ( Ignorable by Annotation )

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

201
        $this->/** @scrutinizer ignore-call */ 
202
               setupCategoryEdits($categoryEditsRepo);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
202
203
        return $this->getFormattedResponse('categoryEdits/result', $this->output);
204
    }
205
206
    /**
207
     * Get edits by a user to pages in given categories.
208
     * @Route(
209
     *   "/categoryedits-contributions/{project}/{username}/{categories}/{start}/{end}/{offset}",
210
     *   name="CategoryContributionsResult",
211
     *   requirements={
212
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
213
     *       "categories"="(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2}))?",
214
     *       "start"="|\d{4}-\d{2}-\d{2}",
215
     *       "end"="|\d{4}-\d{2}-\d{2}",
216
     *       "offset"="|\d{4}-?\d{2}-?\d{2}T?\d{2}:?\d{2}:?\d{2}",
217
     *   },
218
     *   defaults={"start"=false, "end"=false, "offset"=false}
219
     * )
220
     * @param CategoryEditsRepository $categoryEditsRepo
221
     * @return Response
222
     * @codeCoverageIgnore
223
     */
224
    public function categoryContributionsAction(CategoryEditsRepository $categoryEditsRepo): Response
225
    {
226
        $this->setupCategoryEdits($categoryEditsRepo);
0 ignored issues
show
Unused Code introduced by
The call to App\Controller\CategoryE...r::setupCategoryEdits() has too many arguments starting with $categoryEditsRepo. ( Ignorable by Annotation )

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

226
        $this->/** @scrutinizer ignore-call */ 
227
               setupCategoryEdits($categoryEditsRepo);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
227
228
        return $this->render('categoryEdits/contributions.html.twig', $this->output);
229
    }
230
231
    /************************ API endpoints ************************/
232
233
    /**
234
     * Count the number of category edits the given user has made.
235
     * @Route(
236
     *   "/api/user/category_editcount/{project}/{username}/{categories}/{start}/{end}",
237
     *   name="UserApiCategoryEditCount",
238
     *   requirements={
239
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
240
     *       "categories" = "(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2})(?:\/(|\d{4}-\d{2}-\d{2}))?)?$",
241
     *       "start" = "|\d{4}-\d{2}-\d{2}",
242
     *       "end" = "|\d{4}-\d{2}-\d{2}"
243
     *   },
244
     *   defaults={"start" = false, "end" = false}
245
     * )
246
     * @param CategoryEditsRepository $categoryEditsRepo
247
     * @return JsonResponse
248
     * @codeCoverageIgnore
249
     */
250
    public function categoryEditCountApiAction(CategoryEditsRepository $categoryEditsRepo): JsonResponse
251
    {
252
        $this->recordApiUsage('user/category_editcount');
253
254
        $this->setupCategoryEdits($categoryEditsRepo);
0 ignored issues
show
Unused Code introduced by
The call to App\Controller\CategoryE...r::setupCategoryEdits() has too many arguments starting with $categoryEditsRepo. ( Ignorable by Annotation )

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

254
        $this->/** @scrutinizer ignore-call */ 
255
               setupCategoryEdits($categoryEditsRepo);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
255
256
        $ret = [
257
            'total_editcount' => $this->categoryEdits->getEditCount(),
258
            'category_editcount' => $this->categoryEdits->getCategoryEditCount(),
259
        ];
260
261
        return $this->getFormattedApiResponse($ret);
262
    }
263
}
264