Passed
Push — master ( bb3b01...ed8c75 )
by MusikAnimal
06:02
created

AutomatedEditsController::resultAction()   B

Complexity

Conditions 6
Paths 17

Size

Total Lines 64
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
eloc 36
nc 17
nop 4
dl 0
loc 64
rs 8.6346
c 0
b 0
f 0
ccs 0
cts 0
cp 0
crap 42

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file contains only the AutomatedEditsController class.
4
 */
5
6
namespace AppBundle\Controller;
7
8
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
9
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
10
use Symfony\Component\HttpFoundation\Request;
11
use Symfony\Component\HttpFoundation\Response;
12
use Symfony\Component\HttpFoundation\RedirectResponse;
13
use Symfony\Component\HttpFoundation\JsonResponse;
14
use Xtools\AutoEdits;
15
use Xtools\AutoEditsRepository;
16
use Xtools\ProjectRepository;
17
use Xtools\User;
18
use Xtools\UserRepository;
19
use Xtools\Edit;
20
21
/**
22
 * This controller serves the AutomatedEdits tool.
23
 */
24
class AutomatedEditsController extends XtoolsController
25
{
26
27
    /**
28
     * Get the tool's shortname.
29
     * @return string
30
     * @codeCoverageIgnore
31
     */
32
    public function getToolShortname()
33
    {
34
        return 'autoedits';
35
    }
36
37
    /**
38
     * Display the search form.
39
     * @Route("/autoedits", name="autoedits")
40
     * @Route("/autoedits/", name="autoeditsSlash")
41
     * @Route("/automatededits", name="autoeditsLong")
42
     * @Route("/automatededits/", name="autoeditsLongSlash")
43
     * @Route("/autoedits/index.php", name="autoeditsIndexPhp")
44
     * @Route("/automatededits/index.php", name="autoeditsLongIndexPhp")
45
     * @Route("/autoedits/{project}", name="autoeditsProject")
46
     * @param Request $request The HTTP request.
47
     * @return Response
48
     */
49 1
    public function indexAction(Request $request)
50
    {
51 1
        $params = $this->parseQueryParams($request);
52
53
        // Redirect if at minimum project and username are provided.
54 1
        if (isset($params['project']) && isset($params['username'])) {
55
            return $this->redirectToRoute('autoeditsResult', $params);
56
        }
57
58
        // Convert the given project (or default project) into a Project instance.
59 1
        $params['project'] = $this->getProjectFromQuery($params);
60
61 1
        return $this->render('autoEdits/index.html.twig', array_merge([
62 1
            'xtPageTitle' => 'tool-autoedits',
63
            'xtSubtitle' => 'tool-autoedits-desc',
64
            'xtPage' => 'autoedits',
65
66
            // Defaults that will get overriden if in $params.
67
            'namespace' => 0,
68
            'start' => '',
69
            'end' => '',
70 1
        ], $params));
71
    }
72
73
    /**
74
     * Display the results.
75
     * @Route(
76
     *     "/autoedits/{project}/{username}/{namespace}/{start}/{end}", name="autoeditsResult",
77
     *     requirements={
78
     *         "start" = "|\d{4}-\d{2}-\d{2}",
79
     *         "end" = "|\d{4}-\d{2}-\d{2}",
80
     *         "namespace" = "|all|\d+"
81
     *     }
82
     * )
83
     * @param Request $request The HTTP request.
84
     * @param int|string $namespace
85
     * @param null|string $start
86
     * @param null|string $end
87
     * @return RedirectResponse|Response
88
     * @codeCoverageIgnore
89
     */
90
    public function resultAction(Request $request, $namespace = 0, $start = null, $end = null)
91
    {
92
        // Will redirect back to index if the user has too high of an edit count.
93
        $ret = $this->validateProjectAndUser($request, 'autoedits');
94
        if ($ret instanceof RedirectResponse) {
0 ignored issues
show
introduced by
The condition $ret instanceof Symfony\...dation\RedirectResponse can never be false since $ret is always a sub-type of Symfony\Component\HttpFoundation\RedirectResponse.
Loading history...
95
            return $ret;
96
        } else {
97
            list($project, $user) = $ret;
98
        }
99
100
        // 'false' means the dates are optional and returned as 'false' if empty.
101
        list($start, $end) = $this->getUTCFromDateParams($start, $end, false);
102
103
        // We'll want to conditionally show some things in the view if there is a start date.
104
        $hasStartDate = $start > 0;
105
106
        // Format dates as needed by User model, if the date is present.
107
        if ($start !== false) {
108
            $start = date('Y-m-d', $start);
109
        }
110
        if ($end !== false) {
111
            $end = date('Y-m-d', $end);
112
        }
113
114
        // Normalize default namespace.
115
        if ($namespace == '') {
116
            $namespace = 0;
117
        }
118
119
        $autoEdits = new AutoEdits($project, $user, $namespace, $start, $end);
120
        $autoEditsRepo = new AutoEditsRepository();
121
        $autoEditsRepo->setContainer($this->container);
122
        $autoEdits->setRepository($autoEditsRepo);
123
124
        $editCount = $user->countEdits($project, $namespace, $start, $end);
125
126
        // Get individual counts of how many times each tool was used.
127
        // This also includes a wikilink to the tool.
128
        $toolCounts = $autoEdits->getAutomatedCounts();
129
        $toolsTotal = array_reduce($toolCounts, function ($a, $b) {
130
            return $a + $b['count'];
131
        });
132
133
        // Query to get combined (semi)automated using for all edits
134
        //   as some automated edits overlap.
135
        $autoCount = $autoEdits->countAutomatedEdits();
136
137
        $ret = [
138
            'xtPage' => 'autoedits',
139
            'user' => $user,
140
            'project' => $project,
141
            'toolCounts' => $toolCounts,
142
            'toolsTotal' => $toolsTotal,
143
            'autoCount' => $autoCount,
144
            'editCount' => $editCount,
145
            'autoPct' => $editCount ? ($autoCount / $editCount) * 100 : 0,
146
            'hasStartDate' => $hasStartDate,
147
            'start' => $start,
148
            'end' => $end,
149
            'namespace' => $namespace,
150
        ];
151
152
        // Render the view with all variables set.
153
        return $this->render('autoEdits/result.html.twig', $ret);
154
    }
155
156
    /************************ API endpoints ************************/
157
158
    /**
159
     * Count the number of automated edits the given user has made.
160
     * @Route(
161
     *   "/api/user/automated_editcount/{project}/{username}/{namespace}/{start}/{end}/{tools}",
162
     *   requirements={"start" = "|\d{4}-\d{2}-\d{2}", "end" = "|\d{4}-\d{2}-\d{2}"}
163
     * )
164
     * @param Request $request The HTTP request.
165
     * @param int|string $namespace ID of the namespace, or 'all' for all namespaces
166
     * @param string $start In the format YYYY-MM-DD
167
     * @param string $end In the format YYYY-MM-DD
168
     * @param string $tools Non-blank to show which tools were used and how many times.
169
     * @return Response
170
     * @codeCoverageIgnore
171
     */
172
    public function automatedEditCountApiAction(
173
        Request $request,
174
        $namespace = 'all',
175
        $start = '',
176
        $end = '',
177
        $tools = ''
178
    ) {
179
        $this->recordApiUsage('user/automated_editcount');
180
181
        list($project, $user) = $this->validateProjectAndUser($request);
182
183
        $res = [
184
            'project' => $project->getDomain(),
185
            'username' => $user->getUsername(),
186
            'total_editcount' => $user->countEdits($project, $namespace, $start, $end),
187
        ];
188
189
        $autoEdits = new AutoEdits($project, $user, $namespace, $start, $end);
190
        $autoEditsRepo = new AutoEditsRepository();
191
        $autoEditsRepo->setContainer($this->container);
192
        $autoEdits->setRepository($autoEditsRepo);
193
194
        $response = new JsonResponse();
195
        $response->setEncodingOptions(JSON_NUMERIC_CHECK);
196
197
        if ($tools != '') {
198
            $tools = $autoEdits->getAutomatedCounts();
199
            $res['automated_editcount'] = 0;
200
            foreach ($tools as $tool) {
201
                $res['automated_editcount'] += $tool['count'];
202
            }
203
            $res['automated_tools'] = $tools;
204
        } else {
205
            $res['automated_editcount'] = $autoEdits->countAutomatedEdits();
206
        }
207
208
        $res['nonautomated_editcount'] = $res['total_editcount'] - $res['automated_editcount'];
209
210
        $response->setData($res);
211
        return $response;
212
    }
213
214
    /**
215
     * Get non-automated edits for the given user.
216
     * @Route(
217
     *   "/api/user/nonautomated_edits/{project}/{username}/{namespace}/{start}/{end}/{offset}",
218
     *   requirements={
219
     *       "start" = "|\d{4}-\d{2}-\d{2}",
220
     *       "end" = "|\d{4}-\d{2}-\d{2}",
221
     *       "offset" = "\d*"
222
     *   }
223
     * )
224
     * @param Request $request The HTTP request.
225
     * @param int|string $namespace ID of the namespace, or 'all' for all namespaces
226
     * @param string $start In the format YYYY-MM-DD
227
     * @param string $end In the format YYYY-MM-DD
228
     * @param int $offset For pagination, offset results by N edits
229
     * @return Response
230
     * @codeCoverageIgnore
231
     */
232
    public function nonAutomatedEditsApiAction(
233
        Request $request,
234
        $namespace = 0,
235
        $start = '',
236
        $end = '',
237
        $offset = 0
238
    ) {
239
        $this->recordApiUsage('user/nonautomated_edits');
240
241
        // Second parameter causes it return a Redirect to the index if the user has too many edits.
242
        // We only want to do this when looking at the user's overall edits, not just to a specific article.
243
        list($project, $user) = $this->validateProjectAndUser($request);
244
245
        // Reject if they've made too many edits.
246
        if ($user->hasTooManyEdits($project)) {
247
            if ($request->query->get('format') !== 'html') {
248
                return new JsonResponse(
249
                    [
250
                        'error' => 'Unable to show any data. User has made over ' .
251
                            $user->maxEdits() . ' edits.',
252
                    ],
253
                    Response::HTTP_FORBIDDEN
254
                );
255
            }
256
257
            $edits = [];
258
        } else {
259
            $autoEdits = new AutoEdits($project, $user, $namespace, $start, $end);
260
            $autoEditsRepo = new AutoEditsRepository();
261
            $autoEditsRepo->setContainer($this->container);
262
            $autoEdits->setRepository($autoEditsRepo);
263
264
            $edits = $autoEdits->getNonautomatedEdits($offset);
265
        }
266
267
        if ($request->query->get('format') === 'html') {
268
            if ($edits) {
0 ignored issues
show
introduced by
The condition $edits can never be true.
Loading history...
269
                $edits = array_map(function ($attrs) use ($project, $user) {
270
                    $page = $project->getRepository()
271
                        ->getPage($project, $attrs['full_page_title']);
272
                    $pageTitles[] = $attrs['full_page_title'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$pageTitles was never initialized. Although not strictly required by PHP, it is generally a good practice to add $pageTitles = array(); before regardless.
Loading history...
273
                    $attrs['id'] = $attrs['rev_id'];
274
                    $attrs['username'] = $user->getUsername();
275
                    return new Edit($page, $attrs);
276
                }, $edits);
277
            }
278
279
            $response = $this->render('autoEdits/nonautomated_edits.html.twig', [
280
                'edits' => $edits,
281
                'project' => $project,
282
                'maxEdits' => $user->maxEdits(),
283
            ]);
284
            $response->headers->set('Content-Type', 'text/html');
285
            return $response;
286
        }
287
288
        $ret = [
289
            'project' => $project->getDomain(),
290
            'username' => $user->getUsername(),
291
        ];
292
        if ($namespace != '' && $namespace !== 'all') {
293
            $ret['namespace'] = $namespace;
294
        }
295
        if ($start != '') {
296
            $ret['start'] = $start;
297
        }
298
        if ($end != '') {
299
            $ret['end'] = $end;
300
        }
301
        $ret['offset'] = $offset;
302
        $ret['nonautomated_edits'] = $edits;
303
304
        $response = new JsonResponse();
305
        $response->setEncodingOptions(JSON_NUMERIC_CHECK);
306
307
        $response->setData($ret);
308
        return $response;
309
    }
310
}
311