FormTrait   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 263
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 96
c 2
b 0
f 0
dl 0
loc 263
rs 10
wmc 29

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 18 1
A getAuthorEmailConstraints() 0 7 1
A getDoctrine() 0 3 1
A getId() 0 3 1
A defaultStepValidator() 0 26 3
A sanitizeConversation() 0 4 1
A incrementStep() 0 4 1
A showSuccess() 0 5 1
A validCurrentStep() 0 8 2
A getStep() 0 7 2
A showForm() 0 4 1
A validStepOne() 0 3 1
A getShowFormTemplate() 0 14 3
A getNextStep() 0 3 1
A getCurrentStep() 0 5 1
A initForm() 0 26 3
A getType() 0 3 1
A getNextStepFunctionName() 0 8 2
A getReferring() 0 3 1
A getAuthorNameConstraints() 0 7 1
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