PostListController::post()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 9.424
c 0
b 0
f 0
cc 3
nc 3
nop 1
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\PostList;
16
17
use Acme\App\Core\Component\Blog\Application\Query\PostDto;
18
use Acme\App\Core\Component\Blog\Application\Query\PostListQueryInterface;
19
use Acme\App\Core\Component\Blog\Application\Service\PostService;
20
use Acme\App\Core\Component\Blog\Domain\Post\Post;
21
use Acme\App\Core\Port\Auth\Authentication\AuthenticationServiceInterface;
22
use Acme\App\Core\Port\Router\UrlGeneratorInterface;
23
use Acme\App\Core\Port\TemplateEngine\TemplateEngineInterface;
24
use Acme\App\Presentation\Web\Core\Port\FlashMessage\FlashMessageServiceInterface;
25
use Acme\App\Presentation\Web\Core\Port\Form\FormFactoryInterface;
26
use Acme\App\Presentation\Web\Core\Port\Form\FormInterface;
27
use Acme\App\Presentation\Web\Core\Port\Response\ResponseFactoryInterface;
28
use Psr\Http\Message\ResponseInterface;
29
use Psr\Http\Message\ServerRequestInterface;
30
31
/**
32
 * Controller used to manage blog contents in the backend.
33
 *
34
 * Please note that the application backend is developed manually for learning
35
 * purposes. However, in your real Symfony application you should use any of the
36
 * existing bundles that let you generate ready-to-use backends without effort.
37
 *
38
 * See http://knpbundles.com/keyword/admin
39
 *
40
 * @author Ryan Weaver <[email protected]>
41
 * @author Javier Eguiluz <[email protected]>
42
 * @author Herberto Graca <[email protected]>
43
 */
44
class PostListController
45
{
46
    /**
47
     * @var PostService
48
     */
49
    private $postService;
50
51
    /**
52
     * @var FlashMessageServiceInterface
53
     */
54
    private $flashMessageService;
55
56
    /**
57
     * @var UrlGeneratorInterface
58
     */
59
    private $urlGenerator;
60
61
    /**
62
     * @var TemplateEngineInterface
63
     */
64
    private $templateEngine;
65
66
    /**
67
     * @var ResponseFactoryInterface
68
     */
69
    private $responseFactory;
70
71
    /**
72
     * @var FormFactoryInterface
73
     */
74
    private $formFactory;
75
76
    /**
77
     * @var AuthenticationServiceInterface
78
     */
79
    private $authenticationService;
80
81 View Code Duplication
    public function __construct(
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
        PostService $postService,
83
        FlashMessageServiceInterface $flashMessageService,
84
        UrlGeneratorInterface $urlGenerator,
85
        TemplateEngineInterface $templateEngine,
86
        ResponseFactoryInterface $responseFactory,
87
        FormFactoryInterface $formFactory,
88
        AuthenticationServiceInterface $authenticationService
89
    ) {
90
        $this->postService = $postService;
91
        $this->flashMessageService = $flashMessageService;
92
        $this->urlGenerator = $urlGenerator;
93
        $this->templateEngine = $templateEngine;
94
        $this->responseFactory = $responseFactory;
95
        $this->formFactory = $formFactory;
96
        $this->authenticationService = $authenticationService;
97
    }
98
99
    /**
100
     * Lists all Post entities.
101
     *
102
     * This controller responds to two different routes with the same URL:
103
     *     'admin_post_list' is the route with a name that follows the same
104
     *     structure as the rest of the controllers of this class.
105
     *     'admin_index' is a nice shortcut to the backend homepage. This allows
106
     *     to create simpler links in the templates. Moreover, in the future we
107
     *     could move this annotation to any other controller while maintaining
108
     *     the route name and therefore, without breaking any existing link.
109
     */
110
    public function get(PostListQueryInterface $postListQuery): ResponseInterface
111
    {
112
        $postDtoList = $postListQuery->execute($this->authenticationService->getLoggedInUserId())
113
            ->hydrateResultItemsAs(PostDto::class);
114
115
        return $this->templateEngine->renderResponse(
116
            '@Blog/Admin/PostList/get.html.twig',
117
            GetViewModel::fromPostDtoList(...$postDtoList)
118
        );
119
    }
120
121
    /**
122
     * Shows the form to create a new Post entity.
123
     *
124
     * NOTE: the Method annotation is optional, but it's a recommended practice
125
     * to constraint the HTTP methods each controller responds to (by default
126
     * it responds to all methods).
127
     */
128
    public function new(): ResponseInterface
129
    {
130
        $form = $this->createCreatePostForm(new Post());
131
132
        return $this->renderCreatePost($form);
133
    }
134
135
    /**
136
     * Creates a new Post entity.
137
     *
138
     * NOTE: the Method annotation is optional, but it's a recommended practice
139
     * to constraint the HTTP methods each controller responds to (by default
140
     * it responds to all methods).
141
     */
142
    public function post(ServerRequestInterface $request): ResponseInterface
143
    {
144
        $post = new Post();
145
146
        $form = $this->createCreatePostForm($post);
147
148
        $form->handleRequest($request);
149
150
        // the isSubmitted() method is completely optional because the other
151
        // isValid() method already checks whether the form is submitted.
152
        // However, we explicitly add it to improve code readability.
153
        // See https://symfony.com/doc/current/best_practices/forms.html#handling-form-submits
154
        if (!$form->shouldBeProcessed()) {
155
            return $this->renderCreatePost($form);
156
        }
157
158
        $this->postService->create($post, $this->authenticationService->getLoggedInUserId());
159
160
        // Flash messages are used to notify the user about the result of the
161
        // actions. They are deleted automatically from the session as soon
162
        // as they are accessed.
163
        // See https://symfony.com/doc/current/book/controller.html#flash-messages
164
        $this->flashMessageService->success('post.created_successfully');
165
166
        // See https://symfony.com/doc/current/book/forms.html#submitting-forms-with-multiple-buttons
167
        if ($form->clickedButton(FormInterface::BUTTON_NAME_SAVE_AND_CREATE_NEW)) {
168
            return $this->responseFactory->redirectToRoute('admin_post_new');
169
        }
170
171
        return $this->responseFactory->redirectToRoute('admin_post_list');
172
    }
173
174
    protected function createCreatePostForm(Post $post): FormInterface
175
    {
176
        return $this->formFactory->createCreatePostForm(
177
            $post,
178
            ['action' => $this->urlGenerator->generateUrl('admin_post_new_post')]
179
        );
180
    }
181
182
    protected function renderCreatePost(FormInterface $form): ResponseInterface
183
    {
184
        return $this->templateEngine->renderResponse(
185
            '@Blog/Admin/PostList/new.html.twig',
186
            NewViewModel::fromPostAndForm($form)
187
        );
188
    }
189
}
190