DefaultController::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
ccs 10
cts 10
cp 1
cc 1
eloc 9
nc 1
nop 9
crap 1

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
/* Copyright (C) 2015-2017 Michael Giesler, Stephan Kreutzer
3
 *
4
 * This file is part of Dembelo.
5
 *
6
 * Dembelo is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * Dembelo is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU Affero General Public License 3 for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License 3
17
 * along with Dembelo. If not, see <http://www.gnu.org/licenses/>.
18
 */
19
20
declare(strict_types = 1);
21
22
namespace DembeloMain\Controller;
23
24
use DembeloMain\Document\Textnode;
25
use DembeloMain\Document\TextnodeHitch;
26
use DembeloMain\Document\User;
27
use DembeloMain\Model\FavoriteManager;
28
use DembeloMain\Model\FeatureToggle;
29
use DembeloMain\Model\Readpath;
30
use DembeloMain\Model\Repository\TextNodeRepositoryInterface;
31
use DembeloMain\Model\Repository\UserRepositoryInterface;
32
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
33
use Symfony\Component\HttpFoundation\RedirectResponse;
34
use Symfony\Component\HttpFoundation\Response;
35
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
36
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
37
use Symfony\Bundle\FrameworkBundle\Routing\Router;
38
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as Templating;
39
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
40
41
/**
42
 * Class DefaultController
43
 * @Route(service="app.controller_default")
44
 */
45
class DefaultController
46
{
47
    /**
48
     * @var FeatureToggle
49
     */
50
    private $featureToggle;
51
52
    /**
53
     * @var AuthorizationCheckerInterface
54
     */
55
    private $authorizationChecker;
56
57
    /**
58
     * @var UserRepositoryInterface
59
     */
60
    private $userRepository;
61
62
    /**
63
     * @var TextNodeRepositoryInterface
64
     */
65
    private $textnodeRepository;
66
67
    /**
68
     * @var Templating
69
     */
70
    private $templating;
71
72
    /**
73
     * @var Router
74
     */
75
    private $router;
76
77
    /**
78
     * @var TokenStorage
79
     */
80
    private $tokenStorage;
81
82
    /**
83
     * @var Readpath
84
     */
85
    private $readpath;
86
87
    /**
88
     * @var FavoriteManager
89
     */
90
    private $favoriteManager;
91
92
    /**
93
     * DefaultController constructor.
94
     * @param FeatureToggle                 $featureToggle
95
     * @param AuthorizationCheckerInterface $authorizationChecker
96
     * @param UserRepositoryInterface       $userRepository
97
     * @param TextNodeRepositoryInterface   $textNodeRepository
98
     * @param Templating                    $templating
99
     * @param Router                        $router
100
     * @param TokenStorage                  $tokenStorage
101
     * @param Readpath                      $readpath
102
     * @param FavoriteManager               $favoriteManager
103
     */
104 16
    public function __construct(FeatureToggle $featureToggle, AuthorizationCheckerInterface $authorizationChecker, UserRepositoryInterface $userRepository, TextNodeRepositoryInterface $textNodeRepository, Templating $templating, Router $router, TokenStorage $tokenStorage, Readpath $readpath, FavoriteManager $favoriteManager)
105
    {
106 16
        $this->featureToggle = $featureToggle;
107 16
        $this->authorizationChecker = $authorizationChecker;
108 16
        $this->userRepository = $userRepository;
109 16
        $this->textnodeRepository = $textNodeRepository;
110 16
        $this->templating = $templating;
111 16
        $this->router = $router;
112 16
        $this->tokenStorage = $tokenStorage;
113 16
        $this->readpath = $readpath;
114 16
        $this->favoriteManager = $favoriteManager;
115 16
    }
116
117
    /**
118
     * @Route("/themenfeld/{topicId}", name="themenfeld")
119
     *
120
     * @param string $topicId Topic ID from URL
121
     *
122
     * @return RedirectResponse
123
     *
124
     * @throws NotFoundHttpException
125
     */
126 5
    public function readTopicAction($topicId): RedirectResponse
127
    {
128 5
        if ($this->featureToggle->hasFeature('login_needed') && !$this->authorizationChecker->isGranted('ROLE_USER')) {
129 1
            return $this->redirectToRoute('login_route');
130
        }
131
132 4
        $textnode = $this->textnodeRepository->getTextnodeToRead($topicId);
133
134 4
        if (null === $textnode) {
135 1
            throw new NotFoundHttpException(sprintf('No Textnode for Topic \'%s\' found.', $topicId));
136
        }
137
138 3
        $user = $this->getUser();
139 3
        if ($user instanceof User) {
140 1
            $user->setLastTopicId($topicId);
141 1
            $this->userRepository->save($user);
142
        }
143
144 3
        if ($textnode->isFinanceNode()) {
145 1
            return $this->redirectToRoute('financenode', ['textnodeArbitraryId' => $textnode->getArbitraryId()]);
146
        }
147
148 2
        return $this->redirectToRoute('text', array('textnodeArbitraryId' => $textnode->getArbitraryId()));
149
    }
150
151
    /**
152
     * @Route("/text/{textnodeArbitraryId}", name="text")
153
     *
154
     * @param string $textnodeArbitraryId Textnode arbitrary ID from URL
155
     *
156
     * @return Response
157
     *
158
     * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
159
     */
160 4
    public function readTextnodeAction($textnodeArbitraryId): Response
161
    {
162 4
        if ($this->featureToggle->hasFeature('login_needed') && !$this->authorizationChecker->isGranted('ROLE_USER')) {
163 1
            return $this->redirectToRoute('login_route');
164
        }
165
166 3
        $textnode = $this->textnodeRepository->findOneActiveByArbitraryId($textnodeArbitraryId);
167
168 3
        if (null === $textnode) {
169 1
            throw new NotFoundHttpException(sprintf('No Textnode with arbitrary ID \'%s\' found.', $textnodeArbitraryId));
170
        }
171
172 2
        if ($textnode->isFinanceNode()) {
173 1
            return $this->redirectToRoute('financenode', ['textnodeArbitraryId' => $textnode->getArbitraryId()]);
174
        }
175
176 1
        $user = $this->getUser();
177
178 1
        $this->readpath->storeReadpath($textnode, $user);
179 1
        $this->favoriteManager->setFavorite($textnode, $user);
180
181 1
        if ($user instanceof User) {
182
            $this->userRepository->save($user);
183
        }
184
185 1
        $hitches = [];
186
187 1
        $childHitches = $textnode->getChildHitches();
188 1
        $index = 0;
189 1
        foreach ($childHitches as $childHitch) {
190
            $hitchedTextnode = $childHitch->getTargetTextnode();
191
            $hitches[] = [
192
                'index' => $index,
193
                'description' => $childHitch->getDescription(),
194
                'arbitraryId' => $hitchedTextnode->getArbitraryId(),
195
                'isFinanceNode' => $hitchedTextnode->isFinanceNode(),
196
            ];
197
            ++$index;
198
        }
199
200 1
        $showBackButton = $this->showBackButton($textnode);
201
202 1
        return $this->templating->renderResponse(
203 1
            'DembeloMain::default/read.html.twig',
204
            [
205 1
                'textnode' => $textnode,
206 1
                'hitches' => $hitches,
207 1
                'showBackButton' => $showBackButton,
208
            ]
209
        );
210
    }
211
212
    /**
213
     * @Route("/paywall/{textnodeId}/{hitchIndex}", name="paywall")
214
     *
215
     * @param string $textnodeId Textnode ID from URL
216
     * @param string $hitchIndex hitch index
217
     *
218
     * @return Response
219
     */
220
    public function paywallAction($textnodeId, $hitchIndex): Response
221
    {
222
        $hitchedTextnode = $this->getTextnodeForHitchIndex($textnodeId, $hitchIndex);
0 ignored issues
show
Bug introduced by
$hitchIndex of type string is incompatible with the type integer expected by parameter $hitchIndex of DembeloMain\Controller\D...TextnodeForHitchIndex(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

222
        $hitchedTextnode = $this->getTextnodeForHitchIndex($textnodeId, /** @scrutinizer ignore-type */ $hitchIndex);
Loading history...
223
224
        $url = $this->router->generate('text', ['textnodeArbitraryId' => $hitchedTextnode->getArbitraryId()]);
225
226
        $output = [
227
            'url' => $url,
228
        ];
229
230
        return new Response(\json_encode($output));
231
    }
232
233
    /**
234
     * @Route("/back", name="back")
235
     *
236
     * @return RedirectResponse
237
     */
238 6
    public function backAction(): RedirectResponse
239
    {
240 6
        $parentHitch = $this->getParentHitch();
241 6
        if (null === $parentHitch) {
242 4
            return $this->redirectToRoute('mainpage');
243
        }
244 2
        $parentTextnode = $parentHitch->getSourceTextnode();
245 2
        if ($parentTextnode->getAccess()) {
246 1
            return $this->redirectToRoute('themenfeld', ['topicId' => $parentTextnode->getTopicId()]);
247
        }
248
249 1
        return $this->redirectToRoute(
250 1
            'text',
251 1
            array('textnodeArbitraryId' => $parentTextnode->getArbitraryId())
252
        );
253
    }
254
255
    /**
256
     * @Route("/imprint", name="imprint")
257
     *
258
     * @return Response
259
     */
260 1
    public function imprintAction(): Response
261
    {
262 1
        return $this->templating->renderResponse('DembeloMain::default/imprint.html.twig');
263
    }
264
265
    /**
266
     * @param string $route
267
     * @param array  $parameters
268
     * @param int    $status
269
     *
270
     * @return RedirectResponse
271
     */
272 12
    protected function redirectToRoute($route, array $parameters = array(), $status = 302): RedirectResponse
273
    {
274 12
        $url = $this->router->generate($route, $parameters);
275
276 12
        return new RedirectResponse($url, $status);
277
    }
278
279
    /**
280
     * @return User|null
281
     */
282 10
    protected function getUser(): ?User
283
    {
284 10
        if (null === $token = $this->tokenStorage->getToken()) {
285 9
            return null;
286
        }
287
288 1
        if (!\is_object($user = $token->getUser())) {
289
            // e.g. anonymous authentication
290
            return null;
291
        }
292
293 1
        return $user;
294
    }
295
296
    /**
297
     * @param string $textnodeId
298
     * @param int    $hitchIndex
299
     *
300
     * @return Textnode|null
301
     *
302
     * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
303
     */
304
    private function getTextnodeForHitchIndex($textnodeId, $hitchIndex): ?Textnode
305
    {
306
        $textnode = $this->textnodeRepository->findOneActiveById($textnodeId);
307
308
        if (null === $textnode) {
309
            throw new NotFoundHttpException(sprintf('No Textnode with ID \'%s\' found.', $textnodeId));
310
        }
311
312
        /* @var $hitch TextnodeHitch */
313
        $hitch = $textnode->getChildHitches()->get($hitchIndex);
314
315
        return $hitch->getTargetTextnode();
316
    }
317
318
    /**
319
     * @param Textnode $textnode
320
     *
321
     * @return bool
322
     */
323 1
    private function showBackButton(Textnode $textnode): bool
324
    {
325 1
        if (false === $textnode->getAccess()) {
326
            return true;
327
        }
328
        $criteria = [
329 1
            'topic_id' => $textnode->getTopicId(),
330
        ];
331 1
        $accessNodes = $this->textnodeRepository->findBy($criteria);
332
333 1
        return (count($accessNodes) >= 2);
334
    }
335
336
    /**
337
     * @return TextnodeHitch|null
338
     */
339 6
    private function getParentHitch(): ?TextnodeHitch
340
    {
341 6
        $user = $this->getUser();
342 6
        $lastTextnodeId = $this->readpath->getCurrentTextnodeId($user);
343
344 6
        if (null === $lastTextnodeId) {
345 1
            return null;
346
        }
347 5
        $lastTextnode = $this->textnodeRepository->find($lastTextnodeId);
348 5
        if (null === $lastTextnode) {
349 1
            return null;
350
        }
351 4
        $parentHitches = $lastTextnode->getParentHitches();
352 4
        if ($parentHitches->isEmpty()) {
353 1
            return null;
354
        }
355
356 3
        return $parentHitches->first();
357
    }
358
}
359