Passed
Push — master ( 40feff...710ff4 )
by Michael
01:41
created

DefaultController::getUser()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 12
ccs 5
cts 6
cp 0.8333
rs 9.4285
cc 3
eloc 5
nc 3
nop 0
crap 3.0416
1
<?php
2
3
declare(strict_types = 1);
4
5
/* Copyright (C) 2015-2017 Michael Giesler, Stephan Kreutzer
6
 *
7
 * This file is part of Dembelo.
8
 *
9
 * Dembelo is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as published by
11
 * the Free Software Foundation, either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * Dembelo is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Affero General Public License 3 for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License 3
20
 * along with Dembelo. If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
/**
24
 * @package DembeloMain
25
 */
26
27
namespace DembeloMain\Controller;
28
29
use DembeloMain\Document\Textnode;
30
use DembeloMain\Document\User;
31
use DembeloMain\Model\FavoriteManager;
32
use DembeloMain\Model\FeatureToggle;
33
use DembeloMain\Model\Readpath;
34
use DembeloMain\Model\Repository\TextNodeRepositoryInterface;
35
use DembeloMain\Model\Repository\UserRepositoryInterface;
36
use DembeloMain\Service\ReadpathUndoService;
37
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
38
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
39
use Symfony\Component\HttpFoundation\RedirectResponse;
40
use Symfony\Component\HttpFoundation\Response;
41
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
42
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
43
use Symfony\Bundle\FrameworkBundle\Routing\Router;
44
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as Templating;
45
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
46
47
/**
48
 * Class DefaultController
49
 * @Route(service="app.controller_default")
50
 */
51
class DefaultController extends Controller
52
{
53
    /**
54
     * @var FeatureToggle
55
     */
56
    private $featureToggle;
57
58
    /**
59
     * @var AuthorizationCheckerInterface
60
     */
61
    private $authorizationChecker;
62
63
    /**
64
     * @var UserRepositoryInterface
65
     */
66
    private $userRepository;
67
68
    /**
69
     * @var TextNodeRepositoryInterface
70
     */
71
    private $textnodeRepository;
72
73
    /**
74
     * @var Templating
75
     */
76
    private $templating;
77
78
    /**
79
     * @var Router
80
     */
81
    private $router;
82
83
    /**
84
     * @var TokenStorage
85
     */
86
    private $tokenStorage;
87
88
    /**
89
     * @var Readpath
90
     */
91
    private $readpath;
92
93
    /**
94
     * @var ReadpathUndoService
95
     */
96
    private $readpathUndoService;
97
98
    /**
99
     * @var FavoriteManager
100
     */
101
    private $favoriteManager;
102
103
    /**
104
     * DefaultController constructor.
105
     * @param FeatureToggle                 $featureToggle
106
     * @param AuthorizationCheckerInterface $authorizationChecker
107
     * @param UserRepositoryInterface       $userRepository
108
     * @param TextNodeRepositoryInterface   $textNodeRepository
109
     * @param Templating                    $templating
110
     * @param Router                        $router
111
     * @param TokenStorage                  $tokenStorage
112
     * @param Readpath                      $readpath
113
     * @param FavoriteManager               $favoriteManager
114
     * @param ReadpathUndoService           $readpathUndoService
115
     */
116 13
    public function __construct(
117
        FeatureToggle $featureToggle,
118
        AuthorizationCheckerInterface $authorizationChecker,
119
        UserRepositoryInterface $userRepository,
120
        TextNodeRepositoryInterface $textNodeRepository,
121
        Templating $templating,
122
        Router $router,
123
        TokenStorage $tokenStorage,
124
        Readpath $readpath,
125
        FavoriteManager $favoriteManager,
126
        ReadpathUndoService $readpathUndoService
127
    ) {
128 13
        $this->featureToggle = $featureToggle;
129 13
        $this->authorizationChecker = $authorizationChecker;
130 13
        $this->userRepository = $userRepository;
131 13
        $this->textnodeRepository = $textNodeRepository;
132 13
        $this->templating = $templating;
133 13
        $this->router = $router;
134 13
        $this->tokenStorage = $tokenStorage;
135 13
        $this->readpath = $readpath;
136 13
        $this->favoriteManager = $favoriteManager;
137 13
        $this->readpathUndoService = $readpathUndoService;
138 13
    }
139
140
    /**
141
     * @Route("/themenfeld/{topicId}", name="themenfeld")
142
     *
143
     * @param string $topicId Topic ID from URL
144
     *
145
     * @return RedirectResponse
146
     * @throws NotFoundHttpException
147
     */
148 5
    public function readTopicAction($topicId)
149
    {
150 5
        if ($this->featureToggle->hasFeature('login_needed') && !$this->authorizationChecker->isGranted('ROLE_USER')) {
151 1
            return $this->redirectToRoute('login_route');
152
        }
153
154 4
        $textnode = $this->textnodeRepository->getTextnodeToRead($topicId);
155
156 4
        if (null === $textnode) {
157 1
            throw $this->createNotFoundException('No Textnode for Topic \''.$topicId.'\' found.');
158
        }
159
160 3
        $user = $this->getUser();
161 3
        if ($user instanceof User) {
162 1
            $user->setLastTopicId($topicId);
163 1
            $this->userRepository->save($user);
164
        }
165
166 3
        if ($textnode->isFinanceNode()) {
167 1
            return $this->redirectToRoute('financenode', ['textnodeArbitraryId' => $textnode->getArbitraryId()]);
168
        }
169
170 2
        return $this->redirectToRoute('text', array('textnodeArbitraryId' => $textnode->getArbitraryId()));
171
    }
172
173
    /**
174
     * @Route("/text/{textnodeArbitraryId}", name="text")
175
     *
176
     * @param string $textnodeArbitraryId Textnode arbitrary ID from URL
177
     *
178
     * @return string
179
     */
180 4
    public function readTextnodeAction($textnodeArbitraryId)
181
    {
182 4
        if ($this->featureToggle->hasFeature('login_needed') && !$this->authorizationChecker->isGranted('ROLE_USER')) {
183 1
            return $this->redirectToRoute('login_route');
184
        }
185
186 3
        $textnode = $this->textnodeRepository->findOneActiveByArbitraryId($textnodeArbitraryId);
187
188 3
        if (null === $textnode) {
189 1
            throw $this->createNotFoundException('No Textnode with arbitrary ID \''.$textnodeArbitraryId.'\' found.');
190
        }
191
192 2
        if ($textnode->isFinanceNode()) {
193 1
            return $this->redirectToRoute('financenode', ['textnodeArbitraryId' => $textnode->getArbitraryId()]);
194
        }
195
196 1
        $user = $this->getUser();
197
198 1
        $this->readpath->storeReadPath($textnode, $user);
199 1
        $this->favoriteManager->setFavorite($textnode, $user);
200 1
        $this->readpathUndoService->add($textnode->getId());
201
202 1
        if ($user instanceof User) {
203
            $this->userRepository->save($user);
204
        }
205
206 1
        $hitches = [];
207
208 1
        for ($i = 0; $i < $textnode->getHitchCount(); ++$i) {
209 1
            $hitch = $textnode->getHitch($i);
210 1
            $hitchedTextnode = $this->getTextnodeForTextnodeId($hitch['textnodeId']);
211 1
            if (null === $hitchedTextnode) {
212 1
                continue;
213
            }
214
            $hitches[] = [
215
                'index' => $i,
216
                'description' => $hitch['description'],
217
                'arbitraryId' => $hitchedTextnode->getArbitraryId(),
218
                'isFinanceNode' => $hitchedTextnode->isFinanceNode(),
219
            ];
220
        }
221
222 1
        return $this->templating->renderResponse(
223 1
            'DembeloMain::default/read.html.twig',
224
            [
225 1
                'textnode' => $textnode,
226 1
                'hitches' => $hitches,
227
            ]
228
        );
229
    }
230
231
    /**
232
     * @Route("/paywall/{textnodeId}/{hitchIndex}", name="paywall")
233
     *
234
     * @param string $textnodeId Textnode ID from URL
235
     * @param string $hitchIndex hitch index
236
     *
237
     * @return string
238
     */
239
    public function paywallAction($textnodeId, $hitchIndex)
240
    {
241
        $hitchedTextnode = $this->getTextnodeForHitchIndex($textnodeId, $hitchIndex);
242
243
        $url = $this->router->generate('text', ['textnodeArbitraryId' => $hitchedTextnode->getArbitraryId()]);
244
245
        $output = [
246
            'url' => $url,
247
        ];
248
249
        return new Response(\json_encode($output));
250
    }
251
252
    /**
253
     * @Route("/back", name="back")
254
     *
255
     * @return RedirectResponse
256
     */
257 3
    public function backAction()
258
    {
259 3
        if (!$this->readpathUndoService->undo()) {
260 2
            $user = $this->getUser();
261 2
            if (null === $user) {
262 1
                return $this->redirectToRoute('mainpage');
263
            }
264 1
            $topicId = $user->getLastTopicId();
265
266 1
            return $this->redirectToRoute('themenfeld', ['topicId' => $topicId]);
267
        }
268 1
        $currentTextnodeId = $this->readpathUndoService->getCurrentItem();
269 1
        $textnode = $this->textnodeRepository->find($currentTextnodeId);
270
271 1
        return $this->redirectToRoute(
272 1
            'text',
273 1
            array('textnodeArbitraryId' => $textnode->getArbitraryId())
274
        );
275
    }
276
277
    /**
278
     * @Route("/imprint", name="imprint")
279
     *
280
     * @return string
281
     */
282 1
    public function imprintAction()
283
    {
284 1
        return $this->templating->renderResponse('DembeloMain::default/imprint.html.twig');
285
    }
286
287 9
    protected function redirectToRoute($route, array $parameters = array(), $status = 302): RedirectResponse
288
    {
289 9
        $url = $this->router->generate($route, $parameters);
290
291 9
        return new RedirectResponse($url, $status);
292
    }
293
294 6
    protected function getUser(): ?User
295
    {
296 6
        if (null === $token = $this->tokenStorage->getToken()) {
297 4
            return null;
298
        }
299
300 2
        if (!is_object($user = $token->getUser())) {
301
            // e.g. anonymous authentication
302
            return null;
303
        }
304
305 2
        return $user;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $user returns the type object which includes types incompatible with the type-hinted return null|DembeloMain\Document\User.
Loading history...
306
    }
307
308
    private function getTextnodeForHitchIndex($textnodeId, $hitchIndex): ?Textnode
309
    {
310
        $textnode = $this->textnodeRepository->findOneActiveById($textnodeId);
311
312
        if (null === $textnode) {
313
            throw $this->createNotFoundException('No Textnode with ID \''.$textnodeId.'\' found.');
314
        }
315
316
        $hitch = $textnode->getHitch($hitchIndex);
317
318
        return $this->getTextnodeForTextnodeId($hitch['textnodeId']);
319
    }
320
321 1
    private function getTextnodeForTextnodeId($textnodeId): ?Textnode
322
    {
323 1
        return  $this->textnodeRepository->findOneActiveById($textnodeId);
324
    }
325
}
326