Test Failed
Push — dependency-injection ( 15c3c9...81aa7f )
by MusikAnimal
04:12
created

CategoryEditsController::__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\Exception\XtoolsHttpException;
8
use App\Model\CategoryEdits;
9
use App\Repository\CategoryEditsRepository;
10
use Symfony\Component\HttpFoundation\JsonResponse;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\Routing\Annotation\Route;
13
14
/**
15
 * This controller serves the Category Edits tool.
16
 */
17
class CategoryEditsController extends XtoolsController
18
{
19
    protected CategoryEdits $categoryEdits;
20
21
    /** @var string[] The categories, with or without namespace. */
22
    protected array $categories;
23
24
    /** @var array Data that is passed to the view. */
25
    private array $output;
26
27
    /**
28
     * Get the name of the tool's index route.
29
     * This is also the name of the associated model.
30
     * @return string
31
     * @codeCoverageIgnore
32
     */
33
    public function getIndexRoute(): string
34
    {
35
        return 'CategoryEdits';
36
    }
37
38
    /**
39
     * Will redirect back to index if the user has too high of an edit count.
40
     * @return string
41
     */
42
    public function tooHighEditCountRoute(): string
43
    {
44
        return $this->getIndexRoute();
45
    }
46
47
    /**
48
     * Display the search form.
49
     * @Route("/categoryedits", name="CategoryEdits")
50
     * @Route("/categoryedits/{project}", name="CategoryEditsProject")
51
     * @return Response
52
     * @codeCoverageIgnore
53
     */
54
    public function indexAction(): Response
55
    {
56
        // Redirect if at minimum project, username and categories are provided.
57
        if (isset($this->params['project']) && isset($this->params['username']) && isset($this->params['categories'])) {
58
            return $this->redirectToRoute('CategoryEditsResult', $this->params);
59
        }
60
61
        return $this->render('categoryEdits/index.html.twig', array_merge([
62
            'xtPageTitle' => 'tool-categoryedits',
63
            'xtSubtitle' => 'tool-categoryedits-desc',
64
            'xtPage' => 'CategoryEdits',
65
66
            // Defaults that will get overridden if in $params.
67
            'namespace' => 0,
68
            'start' => '',
69
            'end' => '',
70
            'username' => '',
71
            'categories' => '',
72
        ], $this->params, ['project' => $this->project]));
73
    }
74
75
    /**
76
     * Set defaults, and instantiate the CategoryEdits model. This is called at the top of every view action.
77
     * @codeCoverageIgnore
78
     */
79
    private function setupCategoryEdits(CategoryEditsRepository $categoryEditsRepo): void
80
    {
81
        $this->extractCategories();
82
83
        $this->categoryEdits = new CategoryEdits(
84
            $categoryEditsRepo,
85
            $this->project,
86
            $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

86
            /** @scrutinizer ignore-type */ $this->user,
Loading history...
87
            $this->categories,
88
            $this->start,
89
            $this->end,
90
            $this->offset
91
        );
92
93
        $this->output = [
94
            'xtPage' => 'CategoryEdits',
95
            '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

95
            '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...
96
            'project' => $this->project,
97
            'user' => $this->user,
98
            'ce' => $this->categoryEdits,
99
            'is_sub_request' => $this->isSubRequest,
100
        ];
101
    }
102
103
    /**
104
     * Go through the categories and normalize values, and set them on class properties.
105
     * @codeCoverageIgnore
106
     */
107
    private function extractCategories(): void
108
    {
109
        // Split categories by pipe.
110
        $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

110
        $categories = explode('|', /** @scrutinizer ignore-type */ $this->request->get('categories'));
Loading history...
111
112
        // Loop through the given categories, stripping out the namespace.
113
        // If a namespace was removed, it is flagged it as normalize
114
        // We look for the wiki's category namespace name, and the MediaWiki default
115
        // 'Category:', which sometimes is used cross-wiki (because it still works).
116
        $normalized = false;
117
        $nsName = $this->project->getNamespaces()[14].':';
118
        $this->categories = array_map(function ($category) use ($nsName, &$normalized) {
119
            if (0 === strpos($category, $nsName) || 0 === strpos($category, 'Category:')) {
120
                $normalized = true;
121
            }
122
            return preg_replace('/^'.$nsName.'/', '', $category);
123
        }, $categories);
124
125
        // Redirect if normalized, since we don't want the Category: prefix in the URL.
126
        if ($normalized) {
127
            throw new XtoolsHttpException(
128
                '',
129
                $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

129
                $this->generateUrl(/** @scrutinizer ignore-type */ $this->request->get('_route'), array_merge(
Loading history...
130
                    $this->request->attributes->get('_route_params'),
131
                    ['categories' => implode('|', $this->categories)]
132
                ))
133
            );
134
        }
135
    }
136
137
    /**
138
     * Display the results.
139
     * @Route(
140
     *     "/categoryedits/{project}/{username}/{categories}/{start}/{end}/{offset}",
141
     *     name="CategoryEditsResult",
142
     *     requirements={
143
     *         "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
144
     *         "categories"="(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2})(?:\/(|\d{4}-\d{2}-\d{2}))?)?$",
145
     *         "start"="|\d{4}-\d{2}-\d{2}",
146
     *         "end"="|\d{4}-\d{2}-\d{2}",
147
     *         "offset"="|\d{4}-?\d{2}-?\d{2}T?\d{2}:?\d{2}:?\d{2}",
148
     *     },
149
     *     defaults={"start"=false, "end"=false, "offset"=false}
150
     * )
151
     * @param CategoryEditsRepository $categoryEditsRepo
152
     * @return Response
153
     * @codeCoverageIgnore
154
     */
155
    public function resultAction(CategoryEditsRepository $categoryEditsRepo): Response
156
    {
157
        $this->setupCategoryEdits($categoryEditsRepo);
158
159
        return $this->getFormattedResponse('categoryEdits/result', $this->output);
160
    }
161
162
    /**
163
     * Get edits by a user to pages in given categories.
164
     * @Route(
165
     *   "/categoryedits-contributions/{project}/{username}/{categories}/{start}/{end}/{offset}",
166
     *   name="CategoryContributionsResult",
167
     *   requirements={
168
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
169
     *       "categories"="(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2}))?",
170
     *       "start"="|\d{4}-\d{2}-\d{2}",
171
     *       "end"="|\d{4}-\d{2}-\d{2}",
172
     *       "offset"="|\d{4}-?\d{2}-?\d{2}T?\d{2}:?\d{2}:?\d{2}",
173
     *   },
174
     *   defaults={"start"=false, "end"=false, "offset"=false}
175
     * )
176
     * @param CategoryEditsRepository $categoryEditsRepo
177
     * @return Response
178
     * @codeCoverageIgnore
179
     */
180
    public function categoryContributionsAction(CategoryEditsRepository $categoryEditsRepo): Response
181
    {
182
        $this->setupCategoryEdits($categoryEditsRepo);
183
184
        return $this->render('categoryEdits/contributions.html.twig', $this->output);
185
    }
186
187
    /************************ API endpoints ************************/
188
189
    /**
190
     * Count the number of category edits the given user has made.
191
     * @Route(
192
     *   "/api/user/category_editcount/{project}/{username}/{categories}/{start}/{end}",
193
     *   name="UserApiCategoryEditCount",
194
     *   requirements={
195
     *       "username" = "(ipr-.+\/\d+[^\/])|([^\/]+)",
196
     *       "categories" = "(.+?)(?!\/(?:|\d{4}-\d{2}-\d{2})(?:\/(|\d{4}-\d{2}-\d{2}))?)?$",
197
     *       "start" = "|\d{4}-\d{2}-\d{2}",
198
     *       "end" = "|\d{4}-\d{2}-\d{2}"
199
     *   },
200
     *   defaults={"start" = false, "end" = false}
201
     * )
202
     * @param CategoryEditsRepository $categoryEditsRepo
203
     * @return JsonResponse
204
     * @codeCoverageIgnore
205
     */
206
    public function categoryEditCountApiAction(CategoryEditsRepository $categoryEditsRepo): JsonResponse
207
    {
208
        $this->recordApiUsage('user/category_editcount');
209
210
        $this->setupCategoryEdits($categoryEditsRepo);
211
212
        $ret = [
213
            'total_editcount' => $this->categoryEdits->getEditCount(),
214
            'category_editcount' => $this->categoryEdits->getCategoryEditCount(),
215
        ];
216
217
        return $this->getFormattedApiResponse($ret);
218
    }
219
}
220