Passed
Push — master ( 1b5c4f...fe254a )
by MusikAnimal
04:26
created

PagesController::indexAction()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 2
nop 1
dl 0
loc 23
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 9.0856
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' => 'both'
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" = "|noredirects|onlyredirects",
78
     *         "deleted" = "|live|deleted|both",
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 Whether to follow redirects or not.
85
     * @param string $deleted Whether to include deleted pages or not.
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 = 'both',
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
        // Set defaults for 'deleted' and redirect if it is invalid.
105
        if (!in_array($deleted, ['both', 'live', 'deleted'])) {
106
            return $this->redirectToRoute('PagesResult', [
107
                'project' => $project->getDomain(),
108
                'username' => $user->getUsername(),
109
                'namespace' => $namespace,
110
                'redirects' => $redirects,
111
                'deleted' => 'both',
112
                'offset' => $offset,
113
            ]);
114
        }
115
116
        $pages = new Pages(
117
            $project,
118
            $user,
119
            $namespace,
120
            $redirects,
121
            $deleted,
122
            $offset
123
        );
124
        $pages->prepareData();
125
126
        // Assign the values and display the template
127
        return $this->render('pages/result.html.twig', [
128
            'xtPage' => 'pages',
129
            'xtTitle' => $user->getUsername(),
130
            'project' => $project,
131
            'user' => $user,
132
            'summaryColumns' => $this->getSummaryColumns($pages),
133
            'pages' => $pages,
134
            'namespace' => $namespace,
135
        ]);
136
    }
137
138
    /**
139
     * What columns to show in namespace totals table.
140
     * @param  Pages $pages The Pages instance.
141
     * @return string[]
142
     * @codeCoverageIgnore
143
     */
144
    protected function getSummaryColumns(Pages $pages)
145
    {
146
        $summaryColumns = ['namespace'];
147
        if ($pages->getDeleted() === 'deleted') {
148
            // Showing only deleted pages shows only the pages column, as redirects are non-applicable.
149
            $summaryColumns[] = 'pages';
150
        } elseif ($pages->getRedirects() == 'onlyredirects') {
151
            // Don't show redundant pages column if only getting data on redirects or deleted pages.
152
            $summaryColumns[] = 'redirects';
153
        } elseif ($pages->getRedirects() == 'noredirects') {
154
            // Don't show redundant redirects column if only getting data on non-redirects.
155
            $summaryColumns[] = 'pages';
156
        } else {
157
            // Order is important here.
158
            $summaryColumns[] = 'pages';
159
            $summaryColumns[] = 'redirects';
160
        }
161
162
        // Show deleted column only when both deleted and live pages are visible.
163
        if ($pages->getDeleted() === 'both') {
164
            $summaryColumns[] = 'deleted';
165
        }
166
167
        return $summaryColumns;
168
    }
169
170
    /************************ API endpoints ************************/
171
172
    /**
173
     * Get a count of the number of pages created by a user,
174
     * including the number that have been deleted and are redirects.
175
     * @Route("/api/user/pages_count/{project}/{username}/{namespace}/{redirects}/{deleted}", name="PagesApiCount",
176
     *     requirements={"namespace"="|\d+|all"})
177
     * @param Request $request
178
     * @param int|string $namespace The ID of the namespace of the page, or 'all' for all namespaces.
179
     * @param string $redirects One of 'noredirects', 'onlyredirects' or 'all' for both.
180
     * @param string $deleted One of 'live', 'deleted' or 'both'.
181
     * @return Response
182
     * @codeCoverageIgnore
183
     */
184
    public function countPagesApiAction(Request $request, $namespace = 0, $redirects = 'noredirects', $deleted = 'both')
185
    {
186
        $this->recordApiUsage('user/pages_count');
187
188
        $ret = $this->validateProjectAndUser($request);
189
        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...
190
            return $ret;
191
        } else {
192
            list($project, $user) = $ret;
193
        }
194
195
        $pages = new Pages(
196
            $project,
197
            $user,
198
            $namespace,
199
            $redirects,
200
            $deleted
201
        );
202
203
        $response = new JsonResponse();
204
        $response->setEncodingOptions(JSON_NUMERIC_CHECK);
205
        $response->setStatusCode(Response::HTTP_OK);
206
207
        $counts = $pages->getCounts();
208
209
        if ($namespace !== 'all' && isset($counts[$namespace])) {
210
            $counts = $counts[$namespace];
211
        }
212
213
        $ret = [
214
            'project' => $project->getDomain(),
215
            'username' => $user->getUsername(),
216
            'namespace' => $namespace,
217
            'redirects' => $redirects,
218
            'deleted' => $deleted,
219
            'counts' => $counts,
220
        ];
221
222
        $response->setData($ret);
223
224
        return $response;
225
    }
226
227
    /**
228
     * Get the pages created by by a user.
229
     * @Route("/api/user/pages/{project}/{username}/{namespace}/{redirects}/{deleted}/{offset}", name="PagesApi",
230
     *     requirements={"namespace"="|\d+|all"})
231
     * @param Request $request
232
     * @param int|string $namespace The ID of the namespace of the page, or 'all' for all namespaces.
233
     * @param string $redirects One of 'noredirects', 'onlyredirects' or 'all' for both.
234
     * @param string $deleted One of 'live', 'deleted' or 'both'.
235
     * @param int $offset Which page of results to show.
236
     * @return Response
237
     * @codeCoverageIgnore
238
     */
239
    public function getPagesApiAction(
240
        Request $request,
241
        $namespace = 0,
242
        $redirects = 'noredirects',
243
        $deleted = 'both',
244
        $offset = 0
245
    ) {
246
        $this->recordApiUsage('user/pages');
247
248
        // Second parameter causes it return a Redirect to the index if the user has too many edits.
249
        $ret = $this->validateProjectAndUser($request, 'pages');
250
        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...
251
            return $ret;
252
        } else {
253
            list($project, $user) = $ret;
254
        }
255
256
        $pages = new Pages(
257
            $project,
258
            $user,
259
            $namespace,
260
            $redirects,
261
            $deleted,
262
            $offset
263
        );
264
265
        $response = new JsonResponse();
266
        $response->setEncodingOptions(JSON_NUMERIC_CHECK);
267
        $response->setStatusCode(Response::HTTP_OK);
268
269
        $pagesList = $pages->getResults();
270
271
        if ($namespace !== 'all' && isset($pagesList[$namespace])) {
272
            $pagesList = $pagesList[$namespace];
273
        }
274
275
        $ret = [
276
            'project' => $project->getDomain(),
277
            'username' => $user->getUsername(),
278
            'namespace' => $namespace,
279
            'redirects' => $redirects,
280
            'deleted' => $deleted
281
        ];
282
283
        if ($pages->getNumResults() === $pages->resultsPerPage()) {
284
            $ret['continue'] = $offset + 1;
285
        }
286
287
        $ret['pages'] = $pagesList;
288
289
        $response->setData($ret);
290
291
        return $response;
292
    }
293
}
294