PostController::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
cc 1
nc 1
nop 10

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
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Explicit Architecture POC,
7
 * which is created on top of the Symfony Demo application.
8
 *
9
 * (c) Herberto Graça <[email protected]>
10
 *
11
 * For the full copyright and license information, please view the LICENSE
12
 * file that was distributed with this source code.
13
 */
14
15
namespace Acme\App\Presentation\Web\Core\Component\Blog\Admin\Post;
16
17
use Acme\App\Core\Component\Blog\Application\Query\PostQueryInterface;
18
use Acme\App\Core\Component\Blog\Application\Repository\PostRepositoryInterface;
19
use Acme\App\Core\Component\Blog\Application\Service\PostService;
20
use Acme\App\Core\Component\Blog\Domain\Post\PostId;
21
use Acme\App\Core\Port\Auth\Authentication\AuthenticationServiceInterface;
22
use Acme\App\Core\Port\Auth\Authorization\AuthorizationServiceInterface;
23
use Acme\App\Core\Port\Auth\Authorization\ResourceActionVoterInterface;
24
use Acme\App\Core\Port\Router\UrlGeneratorInterface;
25
use Acme\App\Core\Port\TemplateEngine\TemplateEngineInterface;
26
use Acme\App\Presentation\Web\Core\Port\FlashMessage\FlashMessageServiceInterface;
27
use Acme\App\Presentation\Web\Core\Port\Form\FormFactoryInterface;
28
use Acme\App\Presentation\Web\Core\Port\Response\ResponseFactoryInterface;
29
use Psr\Http\Message\ResponseInterface;
30
use Psr\Http\Message\ServerRequestInterface;
31
32
/**
33
 * Controller used to manage blog contents in the backend.
34
 *
35
 * Please note that the application backend is developed manually for learning
36
 * purposes. However, in your real Symfony application you should use any of the
37
 * existing bundles that let you generate ready-to-use backends without effort.
38
 *
39
 * See http://knpbundles.com/keyword/admin
40
 *
41
 * @author Ryan Weaver <[email protected]>
42
 * @author Javier Eguiluz <[email protected]>
43
 * @author Herberto Graca <[email protected]>
44
 */
45
class PostController
46
{
47
    /**
48
     * @var PostService
49
     */
50
    private $postService;
51
52
    /**
53
     * @var FlashMessageServiceInterface
54
     */
55
    private $flashMessageService;
56
57
    /**
58
     * @var UrlGeneratorInterface
59
     */
60
    private $urlGenerator;
61
62
    /**
63
     * @var TemplateEngineInterface
64
     */
65
    private $templateEngine;
66
67
    /**
68
     * @var ResponseFactoryInterface
69
     */
70
    private $responseFactory;
71
72
    /**
73
     * @var FormFactoryInterface
74
     */
75
    private $formFactory;
76
77
    /**
78
     * @var PostRepositoryInterface
79
     */
80
    private $postRepository;
81
82
    /**
83
     * @var AuthorizationServiceInterface
84
     */
85
    private $authorizationService;
86
87
    /**
88
     * @var AuthenticationServiceInterface
89
     */
90
    private $authenticationService;
91
92
    /**
93
     * @var PostQueryInterface
94
     */
95
    private $postQuery;
96
97
    public function __construct(
98
        PostService $postService,
99
        PostRepositoryInterface $postRepository,
100
        FlashMessageServiceInterface $flashMessageService,
101
        UrlGeneratorInterface $urlGenerator,
102
        TemplateEngineInterface $templateEngine,
103
        ResponseFactoryInterface $responseFactory,
104
        FormFactoryInterface $formFactory,
105
        AuthorizationServiceInterface $authorizationService,
106
        AuthenticationServiceInterface $authenticationService,
107
        PostQueryInterface $postQuery
108
    ) {
109
        $this->postService = $postService;
110
        $this->flashMessageService = $flashMessageService;
111
        $this->urlGenerator = $urlGenerator;
112
        $this->templateEngine = $templateEngine;
113
        $this->responseFactory = $responseFactory;
114
        $this->formFactory = $formFactory;
115
        $this->postRepository = $postRepository;
116
        $this->authorizationService = $authorizationService;
117
        $this->authenticationService = $authenticationService;
118
        $this->postQuery = $postQuery;
119
    }
120
121
    /**
122
     * Finds and displays a Post entity.
123
     */
124
    public function get(ServerRequestInterface $request): ResponseInterface
125
    {
126
        $this->authorizationService->denyAccessUnlessGranted(
127
            [],
128
            ResourceActionVoterInterface::SHOW,
129
            'When the user is authenticated, posts can only be shown to their authors.',
130
            $this->postRepository->find(new PostId($request->getAttribute('id')))
131
        );
132
133
        return $this->templateEngine->renderResponse(
134
            '@Blog/Admin/Post/get.html.twig',
135
            $this->postQuery
136
                ->includeAuthor()
137
                ->includeTags()
138
                ->execute(new PostId($request->getAttribute('id')))
139
                ->hydrateSingleResultAs(GetViewModel::class)
140
        );
141
    }
142
143
    /**
144
     * Displays a form to edit an existing Post entity.
145
     */
146
    public function edit(ServerRequestInterface $request): ResponseInterface
147
    {
148
        $post = $this->postRepository->find(new PostId($request->getAttribute('id')));
149
150
        $this->authorizationService->denyAccessUnlessGranted(
151
            [],
152
            ResourceActionVoterInterface::EDIT,
153
            'Posts can only be edited by their authors.',
154
            $post
155
        );
156
157
        $form = $this->formFactory->createEditPostForm(
158
            $post,
159
            ['action' => $this->urlGenerator->generateUrl('admin_post_post', ['id' => (string) $post->getId()])]
160
        );
161
162
        return $this->templateEngine->renderResponse(
163
            '@Blog/Admin/Post/edit.html.twig',
164
            EditViewModel::fromPostAndForm($post, $form)
165
        );
166
    }
167
168
    /**
169
     * Receives data from the form to edit an existing Post entity.
170
     */
171
    public function post(ServerRequestInterface $request): ResponseInterface
172
    {
173
        $post = $this->postRepository->find(new PostId($request->getAttribute('id')));
174
175
        $this->authorizationService->denyAccessUnlessGranted(
176
            [],
177
            ResourceActionVoterInterface::EDIT,
178
            'Posts can only be edited by their authors.',
179
            $post
180
        );
181
182
        $form = $this->formFactory->createEditPostForm($post);
183
        $form->handleRequest($request);
184
185
        if (!($form->shouldBeProcessed())) {
186
            return $this->responseFactory->redirectToRoute('admin_post_edit', ['id' => (string) $post->getId()]);
187
        }
188
189
        $this->flashMessageService->success('post.updated_successfully');
190
191
        return $this->responseFactory->redirectToRoute('admin_post_edit', ['id' => (string) $post->getId()]);
192
    }
193
194
    /**
195
     * Deletes a Post entity.
196
     *
197
     * The Security annotation value is an expression (if it evaluates to false,
198
     * the authorization mechanism will prevent the user accessing this resource).
199
     */
200
    public function delete(ServerRequestInterface $request): ResponseInterface
201
    {
202
        $post = $this->postRepository->find(new PostId($request->getAttribute('id')));
203
204
        $this->authorizationService->denyAccessUnlessGranted(
205
            [],
206
            ResourceActionVoterInterface::DELETE,
207
            'Posts can only be deleted by an admin or the author.',
208
            $post
209
        );
210
211
        if (!$this->authenticationService->isCsrfTokenValid('delete', $request->getParsedBody()['token'] ?? '')) {
212
            return $this->responseFactory->redirectToRoute('admin_post_list');
213
        }
214
215
        $this->postService->delete($post);
216
217
        $this->flashMessageService->success('post.deleted_successfully');
218
219
        return $this->responseFactory->redirectToRoute('admin_post_list');
220
    }
221
}
222