FormTrait::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 1
b 0
f 0
nc 1
nop 8
dl 0
loc 18
rs 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
namespace PiedWeb\ConversationBundle\Form;
4
5
use Doctrine\Bundle\DoctrineBundle\Registry;
6
use PiedWeb\ConversationBundle\Entity\MessageInterface as Message;
7
use Symfony\Bundle\FrameworkBundle\Routing\Router;
8
use Symfony\Component\Form\Extension\Core\Type\FormType;
9
use Symfony\Component\Form\FormBuilderInterface;
10
use Symfony\Component\Form\FormFactory;
11
use Symfony\Component\HttpFoundation\IpUtils;
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
14
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
15
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
16
use Symfony\Component\Security\Core\Security;
17
use Symfony\Component\Validator\Constraints\Email;
18
use Symfony\Component\Validator\Constraints\Length;
19
use Symfony\Component\Validator\Constraints\NotBlank;
20
use Symfony\Contracts\Translation\TranslatorInterface;
21
use Twig\Environment as Twig;
22
23
trait FormTrait
24
{
25
    /**
26
     * Permit to convert integer step to text string for a better readability.
27
     *
28
     * @var array
29
     */
30
    protected static $step = [
31
        1 => 'One',
32
        2 => 'Two',
33
        3 => 'Three',
34
        4 => 'Four',
35
    ];
36
37
    /** @var string */
38
    protected $successMessage = 'conversation.send.success';
39
40
    /** @var Request */
41
    protected $request;
42
43
    /** @var \Doctrine\Bundle\DoctrineBundle\Registry */
44
    protected $doctrine;
45
46
    /** @var Twig */
47
    protected $twig;
48
49
    /** @var TokenStorageInterface */
50
    protected $security;
51
52
    /** @var FormFactory */
53
    protected $formFactory;
54
55
    /** @var TranslatorInterface */
56
    protected $translator;
57
58
    /** @var Router */
59
    protected $router;
60
61
    /** @var int */
62
    protected $currentStep;
63
64
    /** @var int */
65
    protected $messageId;
66
67
    /** @var string */
68
    protected $messageEntity;
69
70
    /** @var Message */
71
    protected $message;
72
73
    public function __construct(
74
        string $messageEntity,
75
        Request $request,
76
        Registry $doctrine,
77
        TokenStorageInterface $security,
78
        FormFactory $formFactory,
79
        Twig $twig,
80
        Router $router,
81
        TranslatorInterface $translator
82
    ) {
83
        $this->request = $request;
84
        $this->doctrine = $doctrine;
85
        $this->security = $security;
86
        $this->formFactory = $formFactory;
87
        $this->twig = $twig;
88
        $this->router = $router;
89
        $this->translator = $translator;
90
        $this->messageEntity = $messageEntity;
91
    }
92
93
    /**
94
     * Initiate Message Entity (or load data from previous message)
95
     * and return form builder instance.
96
     */
97
    protected function initForm(): FormBuilderInterface
98
    {
99
        if (1 === $this->getStep()) {
100
            $this->message = new $this->messageEntity(); // todo, permit to configure it
101
            $this->message->setAuthorIpRaw($this->request->getClientIp() ?? '');
102
            $this->message->setReferring($this->getReferring());
103
        } else {
104
            $this->message = $this->doctrine->getRepository($this->messageEntity)->find($this->getId());
105
            if (!$this->message) {
106
                throw new NotFoundHttpException('An error occured during the validation ('.$this->getId().')');
107
            }
108
            // add a security check ? Comparing current IP and previous one
109
            // IPUtils::checkIp($request->getClientIp()), $this->message->getAuthorIpRaw())
110
            // sinon, passer l'id dans la session plutôt que dans la requête
111
        }
112
113
        $form = $this->formFactory->createBuilder(FormType::class, $this->message, ['csrf_protection' => false]);
114
115
        $form->setAction($this->router->generate('piedweb_cms_conversation', [
116
            'type' => $this->getType(),
117
            'referring' => $this->getReferring(),
118
            'id' => $this->getId(),
119
            'step' => $this->getStep(),
120
        ], UrlGeneratorInterface::ABSOLUTE_URL));
121
122
        return $form;
123
    }
124
125
    public function getCurrentStep(): FormBuilderInterface
126
    {
127
        $currentStepMethod = 'getStep'.self::$step[$this->getStep()];
128
129
        return $this->$currentStepMethod();
130
    }
131
132
    abstract protected function getStepOne(): FormBuilderInterface;
133
134
    /**
135
     * Return rendered response (success or error).
136
     */
137
    public function validCurrentStep($form): string
138
    {
139
        $currentStepMethod = 'valid'.self::$step[$this->getStep()];
140
        if (method_exists($this, $currentStepMethod)) {
141
            return  $this->$currentStepMethod($form);
142
        }
143
144
        return $this->defaultStepValidator($form);
145
    }
146
147
    protected function validStepOne($form)
148
    {
149
        return $this->defaultStepValidator($form);
150
    }
151
152
    protected function defaultStepValidator($form): string
153
    {
154
        if ($form->isValid()) {
155
            $this->sanitizeConversation();
156
            $this->getDoctrine()->getManager()->persist($this->message);
157
            $this->getDoctrine()->getManager()->flush();
158
            $this->messageId = $this->message->getId();
159
160
            if (false !== $this->getNextStepFunctionName()) {
161
                $this->incrementStep();
162
163
                return $this->showForm($this->getCurrentStep()->getForm());
164
                /*
165
                return $this->redirectToRoute('piedweb_cms_conversation', [
166
                    'type' => $this->getType(),
167
                    'id' => $this->message->getId(),
168
                    'step' => $this->getStep() + 1,
169
                ]);*/
170
            }
171
            //$form = $form->createView();
172
173
            return $this->showSuccess();
174
        }
175
176
        // return the form with errors highlighted
177
        return $this->showForm($form);
178
    }
179
180
    public function getShowFormTemplate()
181
    {
182
        $template = '@PiedWebConversation/_'
183
            .$this->getType().$this->getReferring().'Step'.$this->getStep().'.html.twig';
184
185
        if (!$this->twig->getLoader()->exists($template)) {
186
            $template = '@PiedWebConversation/_'.$this->getType().'Step'.$this->getStep().'.html.twig';
187
        }
188
189
        if (!$this->twig->getLoader()->exists($template)) {
190
            $template = '@PiedWebConversation/_conversation.html.twig';
191
        }
192
193
        return $template;
194
    }
195
196
    public function showForm($form): string
197
    {
198
        return $this->twig->render($this->getShowFormTemplate(), [
199
            'conversation' => $form->createView(),
200
        ]);
201
    }
202
203
    protected function showSuccess(): string
204
    {
205
        return $this->twig->render('@PiedWebConversation/_alert.html.twig', [
206
            'message' => $this->translator->trans($this->successMessage),
207
            'context' => 'success',
208
        ]);
209
    }
210
211
    protected function getNextStepFunctionName()
212
    {
213
        $getFormMethod = 'getStep'.self::$step[$this->getNextStep()];
214
        if (!method_exists($this, $getFormMethod)) {
215
            return false;
216
        }
217
218
        return $getFormMethod;
219
    }
220
221
    protected function getNextStep()
222
    {
223
        return $this->getStep() + 1;
224
    }
225
226
    protected function sanitizeConversation()
227
    {
228
        $this->message->setContent(
229
            htmlspecialchars($this->message->getContent())
230
        );
231
    }
232
233
    protected function getStep()
234
    {
235
        if (null !== $this->currentStep) {
236
            return $this->currentStep;
237
        }
238
239
        return $this->currentStep = $this->request->query->getInt('step', 1);
240
    }
241
242
    protected function incrementStep()
243
    {
244
        //$this->request->set('step', $this->getStep()+1)
245
        ++$this->currentStep;
246
    }
247
248
    protected function getId()
249
    {
250
        return $this->messageId ?? $this->request->query->getInt('id', 0);
251
    }
252
253
    protected function getReferring()
254
    {
255
        return $this->request->get('referring');
256
    }
257
258
    protected function getType()
259
    {
260
        return $this->request->get('type');
261
    }
262
263
    protected function getDoctrine()
264
    {
265
        return $this->doctrine;
266
    }
267
268
    protected function getAuthorNameConstraints()
269
    {
270
        return [
271
            new NotBlank(),
272
            new Length([
273
                'max' => 100,
274
                'maxMessage' => 'conversation.name.long',
275
            ]),
276
        ];
277
    }
278
279
    protected function getAuthorEmailConstraints()
280
    {
281
        return [
282
            new NotBlank(),
283
            new Email([
284
                'message' => 'user.email.invalid',
285
                'mode' => 'strict',
286
            ]),
287
        ];
288
    }
289
}
290