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

PagesController::resultAction()   B

Complexity

Conditions 4
Paths 3

Size

Total Lines 49
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 30
nc 3
nop 5
dl 0
loc 49
ccs 0
cts 0
cp 0
crap 20
rs 8.7972
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the PagesController class.
4
 */
5
6
namespace AppBundle\Controller;
7
8
use DateTime;
9
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
10
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
11
use Symfony\Component\HttpFoundation\Request;
12
use Symfony\Component\HttpFoundation\Response;
13
use Symfony\Component\HttpFoundation\RedirectResponse;
14
use Symfony\Component\HttpFoundation\JsonResponse;
15
use Xtools\ProjectRepository;
16
use Xtools\UserRepository;
17
use Xtools\Pages;
18
19
/**
20
 * This controller serves the Pages tool.
21
 */
22
class PagesController extends XtoolsController
23
{
24
    const RESULTS_PER_PAGE = 1000;
25
26
    /**
27
     * Get the tool's shortname.
28
     * @return string
29
     * @codeCoverageIgnore
30
     */
31
    public function getToolShortname()
32
    {
33
        return 'pages';
34
    }
35
36
    /**
37
     * Display the form.
38
     * @Route("/pages", name="pages")
39
     * @Route("/pages", name="Pages")
40
     * @Route("/pages/", name="PagesSlash")
41
     * @Route("/pages/index.php", name="PagesIndexPhp")
42
     * @Route("/pages/{project}", name="PagesProject")
43
     * @param Request $request
44
     * @return Response
45
     */
46 1
    public function indexAction(Request $request)
47
    {
48 1
        $params = $this->parseQueryParams($request);
49
50
        // Redirect if at minimum project and username are given.
51 1
        if (isset($params['project']) && isset($params['username'])) {
52
            return $this->redirectToRoute('PagesResult', $params);
53
        }
54
55
        // Convert the given project (or default project) into a Project instance.
56 1
        $params['project'] = $this->getProjectFromQuery($params);
57
58
        // Otherwise fall through.
59 1
        return $this->render('pages/index.html.twig', array_merge([
60 1
            'xtPageTitle' => 'tool-pages',
61
            'xtSubtitle' => 'tool-pages-desc',
62
            'xtPage' => 'pages',
63
64
            // Defaults that will get overriden if in $params.
65
            'namespace' => 0,
66
            'redirects' => 'noredirects',
67
            'deleted' => 'all'
68 1
        ], $params));
69
    }
70
71
    /**
72
     * Display the results.
73
     * @Route(
74
     *     "/pages/{project}/{username}/{namespace}/{redirects}/{deleted}/{offset}", name="PagesResult",
75
     *     requirements={
76
     *         "namespace" = "|all|\d+",
77
     *         "redirects" = "|[^/]++",
78
     *         "deleted" = "|all|live|deleted",
79
     *         "offset" = "|\d+"
80
     *     }
81
     * )
82
     * @param Request $request
83
     * @param string|int $namespace The ID of the namespace, or 'all' for all namespaces.
84
     * @param string $redirects One of 'noredirects', 'onlyredirects' or 'all' for both.
85
     * @param string $deleted One of 'live', 'deleted' or 'all' for both.
86
     * @param int $offset Which page of results to show, when the results are so large they are paginated.
87
     * @return RedirectResponse|Response
88
     * @codeCoverageIgnore
89
     */
90
    public function resultAction(
91
        Request $request,
92
        $namespace = '0',
93
        $redirects = 'noredirects',
94
        $deleted = 'all',
95
        $offset = 0
96
    ) {
97
        $ret = $this->validateProjectAndUser($request, 'pages');
98
        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...
99
            return $ret;
100
        } else {
101
            list($project, $user) = $ret;
102
        }
103
104
        // Check for legacy values for 'redirects', and redirect
105
        // back with correct values if need be. This could be refactored
106
        // out to XtoolsController, but this is the only tool in the suite
107
        // that deals with redirects, so we'll keep it confined here.
108
        $validRedirects = ['', 'noredirects', 'onlyredirects', 'all'];
109
        if ($redirects === 'none' || !in_array($redirects, $validRedirects)) {
110
            return $this->redirectToRoute('PagesResult', [
111
                'project' => $project->getDomain(),
112
                'username' => $user->getUsername(),
113
                'namespace' => $namespace,
114
                'redirects' => 'noredirects',
115
                'deleted' => $deleted,
116
                'offset' => $offset,
117
            ]);
118
        }
119
120
        $pages = new Pages(
121
            $project,
122
            $user,
123
            $namespace,
124
            $redirects,
125
            $deleted,
126
            $offset
127
        );
128
        $pages->prepareData();
129
130
        // Assign the values and display the template
131
        return $this->render('pages/result.html.twig', [
132
            'xtPage' => 'pages',
133
            'xtTitle' => $user->getUsername(),
134
            'project' => $project,
135
            'user' => $user,
136
            'summaryColumns' => $this->getSummaryColumns($pages),
137
            'pages' => $pages,
138
            'namespace' => $namespace,
139
        ]);
140
    }
141
142
    /**
143
     * What columns to show in namespace totals table.
144
     * @param  Pages $pages The Pages instance.
145
     * @return string[]
146
     * @codeCoverageIgnore
147
     */
148
    protected function getSummaryColumns(Pages $pages)
149
    {
150
        $summaryColumns = ['namespace'];
151
        if ($pages->getDeleted() === 'deleted') {
152
            // Showing only deleted pages shows only the deleted column, as redirects are non-applicable.
153
            $summaryColumns[] = 'deleted';
154
        } elseif ($pages->getRedirects() == 'onlyredirects') {
155
            // Don't show redundant pages column if only getting data on redirects or deleted pages.
156
            $summaryColumns[] = 'redirects';
157
        } elseif ($pages->getRedirects() == 'noredirects') {
158
            // Don't show redundant redirects column if only getting data on non-redirects.
159
            $summaryColumns[] = 'pages';
160
        } else {
161
            // Order is important here.
162
            $summaryColumns[] = 'pages';
163
            $summaryColumns[] = 'redirects';
164
        }
165
166
        // Show deleted column only when both deleted and live pages are visible.
167
        if ($pages->getDeleted() === 'all') {
168
            $summaryColumns[] = 'deleted';
169
        }
170
171
        return $summaryColumns;
172
    }
173
174
    /************************ API endpoints ************************/
175
176
    /**
177
     * Get a count of the number of pages created by a user,
178
     * including the number that have been deleted and are redirects.
179
     * @Route("/api/user/pages_count/{project}/{username}/{namespace}/{redirects}/{deleted}", name="PagesApiCount",
180
     *     requirements={"namespace"="|\d+|all"})
181
     * @param Request $request
182
     * @param int|string $namespace The ID of the namespace of the page, or 'all' for all namespaces.
183
     * @param string $redirects One of 'noredirects', 'onlyredirects' or 'all' for both.
184
     * @param string $deleted One of 'live', 'deleted' or 'all' for both.
185
     * @return Response
186
     * @codeCoverageIgnore
187
     */
188
    public function countPagesApiAction(Request $request, $namespace = 0, $redirects = 'noredirects', $deleted = 'all')
189
    {
190
        $this->recordApiUsage('user/pages_count');
191
192
        $ret = $this->validateProjectAndUser($request);
193
        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...
194
            return $ret;
195
        } else {
196
            list($project, $user) = $ret;
197
        }
198
199
        $pages = new Pages(
200
            $project,
201
            $user,
202
            $namespace,
203
            $redirects,
204
            $deleted
205
        );
206
207
        $response = new JsonResponse();
208
        $response->setEncodingOptions(JSON_NUMERIC_CHECK);
209
        $response->setStatusCode(Response::HTTP_OK);
210
211
        $counts = $pages->getCounts();
212
213
        if ($namespace !== 'all' && isset($counts[$namespace])) {
214
            $counts = $counts[$namespace];
215
        }
216
217
        $ret = [
218
            'project' => $project->getDomain(),
219
            'username' => $user->getUsername(),
220
            'namespace' => $namespace,
221
            'redirects' => $redirects,
222
            'deleted' => $deleted,
223
            'counts' => $counts,
224
        ];
225
226
        $response->setData($ret);
227
228
        return $response;
229
    }
230
231
    /**
232
     * Get the pages created by by a user.
233
     * @Route("/api/user/pages/{project}/{username}/{namespace}/{redirects}/{deleted}/{offset}", name="PagesApi",
234
     *     requirements={"namespace"="|\d+|all"})
235
     * @param Request $request
236
     * @param int|string $namespace The ID of the namespace of the page, or 'all' for all namespaces.
237
     * @param string $redirects One of 'noredirects', 'onlyredirects' or 'all' for both.
238
     * @param string $deleted One of 'live', 'deleted' or blank for both.
239
     * @param int $offset Which page of results to show.
240
     * @return Response
241
     * @codeCoverageIgnore
242
     */
243
    public function getPagesApiAction(
244
        Request $request,
245
        $namespace = 0,
246
        $redirects = 'noredirects',
247
        $deleted = 'all',
248
        $offset = 0
249
    ) {
250
        $this->recordApiUsage('user/pages');
251
252
        // Second parameter causes it return a Redirect to the index if the user has too many edits.
253
        $ret = $this->validateProjectAndUser($request, 'pages');
254
        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...
255
            return $ret;
256
        } else {
257
            list($project, $user) = $ret;
258
        }
259
260
        $pages = new Pages(
261
            $project,
262
            $user,
263
            $namespace,
264
            $redirects,
265
            $deleted,
266
            $offset
267
        );
268
269
        $response = new JsonResponse();
270
        $response->setEncodingOptions(JSON_NUMERIC_CHECK);
271
        $response->setStatusCode(Response::HTTP_OK);
272
273
        $pagesList = $pages->getResults();
274
275
        if ($namespace !== 'all' && isset($pagesList[$namespace])) {
276
            $pagesList = $pagesList[$namespace];
277
        }
278
279
        $ret = [
280
            'project' => $project->getDomain(),
281
            'username' => $user->getUsername(),
282
            'namespace' => $namespace,
283
            'redirects' => $redirects,
284
            'deleted' => $deleted
285
        ];
286
287
        if ($pages->getNumResults() === $pages->resultsPerPage()) {
288
            $ret['continue'] = $offset + 1;
289
        }
290
291
        $ret['pages'] = $pagesList;
292
293
        $response->setData($ret);
294
295
        return $response;
296
    }
297
}
298