Passed
Push — master ( e6ce91...429907 )
by MusikAnimal
04:46
created

AutomatedEditsController::setupAutoEdits()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 38
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 26
nc 2
nop 0
dl 0
loc 38
ccs 0
cts 0
cp 0
crap 12
rs 9.504
c 0
b 0
f 0
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\Component\DependencyInjection\ContainerInterface;
10
use Symfony\Component\HttpFoundation\JsonResponse;
11
use Symfony\Component\HttpFoundation\RedirectResponse;
12
use Symfony\Component\HttpFoundation\RequestStack;
13
use Symfony\Component\HttpFoundation\Response;
14
use Xtools\AutoEdits;
15
use Xtools\AutoEditsRepository;
16
17
/**
18
 * This controller serves the AutomatedEdits tool.
19
 */
20
class AutomatedEditsController extends XtoolsController
21
{
22
    /** @var AutoEdits The AutoEdits instance. */
23
    protected $autoEdits;
24
25
    /** @var array Data that is passed to the view. */
26
    private $output;
27
28
    /**
29
     * Get the name of the tool's index route.
30
     * This is also the name of the associated model.
31
     * @return string
32
     * @codeCoverageIgnore
33
     */
34
    public function getIndexRoute()
35
    {
36
        return 'AutoEdits';
37
    }
38
39
    /**
40
     * AutomatedEditsController constructor.
41
     * @param RequestStack $requestStack
42
     * @param ContainerInterface $container
43
     */
44 1
    public function __construct(RequestStack $requestStack, ContainerInterface $container)
45
    {
46
        // This will cause the tool to redirect back to the index page, with an error,
47
        // if the user has too high of an edit count.
48 1
        $this->tooHighEditCountAction = $this->getIndexRoute();
49
50 1
        parent::__construct($requestStack, $container);
51 1
    }
52
53
    /**
54
     * Display the search form.
55
     * @Route("/autoedits", name="AutoEdits")
56
     * @Route("/autoedits/", name="AutoEditsSlash")
57
     * @Route("/automatededits", name="AutoEditsLong")
58
     * @Route("/automatededits/", name="AutoEditsLongSlash")
59
     * @Route("/autoedits/index.php", name="AutoEditsIndexPhp")
60
     * @Route("/automatededits/index.php", name="AutoEditsLongIndexPhp")
61
     * @Route("/autoedits/{project}", name="AutoEditsProject")
62
     * @return Response
63
     */
64 1
    public function indexAction()
65
    {
66
        // Redirect if at minimum project and username are provided.
67 1
        if (isset($this->params['project']) && isset($this->params['username'])) {
68
            return $this->redirectToRoute('AutoEditsResult', $this->params);
69
        }
70
71 1
        return $this->render('autoEdits/index.html.twig', array_merge([
72 1
            'xtPageTitle' => 'tool-autoedits',
73
            'xtSubtitle' => 'tool-autoedits-desc',
74
            'xtPage' => 'autoedits',
75
76
            // Defaults that will get overridden if in $this->params.
77
            'username' => '',
78
            'namespace' => 0,
79
            'start' => '',
80
            'end' => '',
81 1
        ], $this->params, ['project' => $this->project]));
82
    }
83
84
    /**
85
     * Set defaults, and instantiate the AutoEdits model. This is called at the top of every view action.
86
     * @codeCoverageIgnore
87
     */
88
    private function setupAutoEdits()
89
    {
90
        $tool = $this->request->query->get('tool', null);
91
92
        $autoEditsRepo = new AutoEditsRepository();
93
        $autoEditsRepo->setContainer($this->container);
94
95
        // Validate tool.
96
        // FIXME: instead of redirecting to index page, show result page listing all tools for that project,
97
        //  clickable to show edits by the user, etc.
98
        if ($tool && !isset($autoEditsRepo->getTools($this->project)[$tool])) {
99
            $docUrl = $this->generateUrl('ProjectApiAutoEditsTools', ['project' => $this->params['project']]);
100
            $this->throwXtoolsException(
101
                $this->getIndexRoute(),
102
                "No known tool with name '$tool'. For available tools, use $docUrl",
103
                ['no-result', $tool],
104
                'tool'
105
            );
106
        }
107
108
        $this->autoEdits = new AutoEdits(
109
            $this->project,
110
            $this->user,
111
            $this->namespace,
112
            $this->start,
113
            $this->end,
114
            $tool,
115
            $this->offset
116
        );
117
        $this->autoEdits->setRepository($autoEditsRepo);
118
119
        $this->output = [
120
            'xtPage' => 'autoedits',
121
            'xtTitle' => $this->user->getUsername(),
122
            'project' => $this->project,
123
            'user' => $this->user,
124
            'ae' => $this->autoEdits,
125
            'is_sub_request' => $this->isSubRequest,
126
        ];
127
    }
128
129
    /**
130
     * Display the results.
131
     * @Route(
132
     *     "/autoedits/{project}/{username}/{namespace}/{start}/{end}", name="AutoEditsResult",
133
     *     requirements={
134
     *         "namespace"="|all|\d+",
135
     *         "start"="|\d{4}-\d{2}-\d{2}",
136
     *         "end"="|\d{4}-\d{2}-\d{2}",
137
     *     },
138
     *     defaults={"namespace"=0, "start"=false, "end"=false}
139
     * )
140
     * @return Response
141
     * @codeCoverageIgnore
142
     */
143
    public function resultAction()
144
    {
145
        // Will redirect back to index if the user has too high of an edit count.
146
        $this->setupAutoEdits();
147
148
        // Render the view with all variables set.
149
        return $this->render('autoEdits/result.html.twig', $this->output);
150
    }
151
152
    /**
153
     * Get non-automated edits for the given user.
154
     * @Route(
155
     *   "/nonautoedits-contributions/{project}/{username}/{namespace}/{start}/{end}/{offset}",
156
     *   name="NonAutoEditsContributionsResult",
157
     *   requirements={
158
     *       "namespace"="|all|\d+",
159
     *       "start"="|\d{4}-\d{2}-\d{2}",
160
     *       "end"="|\d{4}-\d{2}-\d{2}",
161
     *       "offset"="\d*"
162
     *   },
163
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=0}
164
     * )
165
     * @return Response|RedirectResponse
166
     * @codeCoverageIgnore
167
     */
168
    public function nonAutomatedEditsAction()
169
    {
170
        $this->setupAutoEdits();
171
172
        return $this->render('autoEdits/nonautomated_edits.html.twig', $this->output);
173
    }
174
175
    /**
176
     * Get automated edits for the given user using the given tool.
177
     * @Route(
178
     *   "/autoedits-contributions/{project}/{username}/{namespace}/{start}/{end}/{offset}",
179
     *   name="AutoEditsContributionsResult",
180
     *   requirements={
181
     *       "namespace"="|all|\d+",
182
     *       "start"="|\d{4}-\d{2}-\d{2}",
183
     *       "end"="|\d{4}-\d{2}-\d{2}",
184
     *       "offset"="\d*"
185
     *   },
186
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=0}
187
     * )
188
     * @return Response|RedirectResponse
189
     * @codeCoverageIgnore
190
     */
191
    public function automatedEditsAction()
192
    {
193
        $this->setupAutoEdits();
194
195
        return $this->render('autoEdits/automated_edits.html.twig', $this->output);
196
    }
197
198
    /************************ API endpoints ************************/
199
200
    /**
201
     * Get a list of the automated tools and their regex/tags/etc.
202
     * @Route("/api/user/automated_tools/{project}", name="UserApiAutoEditsTools")
203
     * @Route("/api/project/automated_tools/{project}", name="ProjectApiAutoEditsTools")
204
     * @return JsonResponse
205
     * @codeCoverageIgnore
206
     */
207
    public function automatedToolsApiAction()
208
    {
209
        $this->recordApiUsage('user/automated_tools');
210
211
        $aeh = $this->container->get('app.automated_edits_helper');
212
        return new JsonResponse($aeh->getTools($this->project));
213
    }
214
215
    /**
216
     * Count the number of automated edits the given user has made.
217
     * @Route(
218
     *   "/api/user/automated_editcount/{project}/{username}/{namespace}/{start}/{end}/{tools}",
219
     *   name="UserApiAutoEditsCount",
220
     *   requirements={
221
     *       "namespace"="|all|\d+",
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
     * @param string $tools Non-blank to show which tools were used and how many times.
228
     * @return JsonResponse
229
     * @codeCoverageIgnore
230
     */
231
    public function automatedEditCountApiAction($tools = '')
232
    {
233
        $this->recordApiUsage('user/automated_editcount');
234
235
        $this->setupAutoEdits();
236
237
        $ret = [
238
            'total_editcount' => $this->autoEdits->getEditCount(),
239
            'automated_editcount' => $this->autoEdits->getAutomatedCount(),
240
        ];
241
        $ret['nonautomated_editcount'] = $ret['total_editcount'] - $ret['automated_editcount'];
242
243
        if ($tools != '') {
244
            $tools = $this->autoEdits->getToolCounts();
245
            $ret['automated_tools'] = $tools;
246
        }
247
248
        return $this->getFormattedApiResponse($ret);
249
    }
250
251
    /**
252
     * Get non-automated edits for the given user.
253
     * @Route(
254
     *   "/api/user/nonautomated_edits/{project}/{username}/{namespace}/{start}/{end}/{offset}",
255
     *   name="UserApiNonAutoEdits",
256
     *   requirements={
257
     *       "namespace"="|all|\d+",
258
     *       "start"="|\d{4}-\d{2}-\d{2}",
259
     *       "end"="|\d{4}-\d{2}-\d{2}",
260
     *       "offset"="\d*"
261
     *   },
262
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=0}
263
     * )
264
     * @return JsonResponse
265
     * @codeCoverageIgnore
266
     */
267
    public function nonAutomatedEditsApiAction()
268
    {
269
        $this->recordApiUsage('user/nonautomated_edits');
270
271
        $this->setupAutoEdits();
272
273
        $ret = array_map(function ($rev) {
274
            return array_merge([
275
                'full_page_title' => $this->getPageFromNsAndTitle($rev['page_namespace'], $rev['page_title'], true),
276
            ], $rev);
277
        }, $this->autoEdits->getNonAutomatedEdits(true));
278
279
        return $this->getFormattedApiResponse(['nonautomated_edits' => $ret]);
280
    }
281
282
    /**
283
     * Get (semi-)automated edits for the given user, optionally using the given tool.
284
     * @Route(
285
     *   "/api/user/automated_edits/{project}/{username}/{namespace}/{start}/{end}/{offset}",
286
     *   name="UserApiAutoEdits",
287
     *   requirements={
288
     *       "namespace"="|all|\d+",
289
     *       "start"="|\d{4}-\d{2}-\d{2}",
290
     *       "end"="|\d{4}-\d{2}-\d{2}",
291
     *       "offset"="\d*"
292
     *   },
293
     *   defaults={"namespace"=0, "start"=false, "end"=false, "offset"=0}
294
     * )
295
     * @return Response
296
     * @codeCoverageIgnore
297
     */
298
    public function automatedEditsApiAction()
299
    {
300
        $this->recordApiUsage('user/automated_edits');
301
302
        $this->setupAutoEdits();
303
304
        $ret = [];
305
306
        if ($this->autoEdits->getTool()) {
307
            $ret['tool'] = $this->autoEdits->getTool();
308
        }
309
310
        $ret['automated_edits'] = array_map(function ($rev) {
311
            return array_merge([
312
                'full_page_title' => $this->getPageFromNsAndTitle($rev['page_namespace'], $rev['page_title'], true),
313
            ], $rev);
314
        }, $this->autoEdits->getAutomatedEdits(true));
315
316
        return $this->getFormattedApiResponse($ret);
317
    }
318
}
319