DynamicFormService::dispatchFormEvent()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of the login-cidadao project or it's bundles.
4
 *
5
 * (c) Guilherme Donato <guilhermednt on github>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace LoginCidadao\DynamicFormBundle\Service;
12
13
use Doctrine\ORM\EntityManagerInterface;
14
use FOS\UserBundle\Event\FilterUserResponseEvent;
15
use FOS\UserBundle\Event\FormEvent;
16
use FOS\UserBundle\Event\GetResponseUserEvent;
17
use FOS\UserBundle\FOSUserEvents;
18
use FOS\UserBundle\Model\UserManagerInterface;
19
use LoginCidadao\DynamicFormBundle\DynamicFormEvents;
20
use LoginCidadao\CoreBundle\Entity\City;
21
use LoginCidadao\CoreBundle\Entity\Country;
22
use LoginCidadao\CoreBundle\Entity\PersonAddress;
23
use LoginCidadao\CoreBundle\Entity\State;
24
use LoginCidadao\CoreBundle\Entity\StateRepository;
25
use LoginCidadao\CoreBundle\Model\IdCardInterface;
26
use LoginCidadao\CoreBundle\Model\PersonInterface;
27
use LoginCidadao\CoreBundle\Model\LocationSelectData;
28
use LoginCidadao\DynamicFormBundle\Form\DynamicFormBuilder;
29
use LoginCidadao\DynamicFormBundle\Model\DynamicFormData;
30
use LoginCidadao\OAuthBundle\Model\ClientInterface;
31
use LoginCidadao\OpenIDBundle\Task\CompleteUserInfoTask;
32
use LoginCidadao\TaskStackBundle\Service\TaskStackManagerInterface;
33
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
34
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
35
use Symfony\Component\Form\FormInterface;
36
use Symfony\Component\HttpFoundation\RedirectResponse;
37
use Symfony\Component\HttpFoundation\Request;
38
use Symfony\Component\HttpFoundation\Response;
39
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
40
use Symfony\Component\Routing\RouterInterface;
41
42
class DynamicFormService implements DynamicFormServiceInterface
43
{
44
    /** @var EntityManagerInterface */
45
    private $em;
46
47
    /** @var EventDispatcherInterface */
48
    private $dispatcher;
49
50
    /** @var UserManagerInterface */
51
    private $userManager;
52
53
    /** @var TaskStackManagerInterface */
54
    private $taskStackManager;
55
56
    /** @var DynamicFormBuilder */
57
    private $dynamicFormBuilder;
58
59
    /** @var RouterInterface */
60
    private $router;
61
62
    /**
63
     * DynamicFormService constructor.
64
     * @param EntityManagerInterface $em
65
     * @param EventDispatcherInterface $dispatcher
66
     * @param UserManagerInterface $userManager
67
     * @param TaskStackManagerInterface $taskStackManager
68
     * @param DynamicFormBuilder $dynamicFormBuilder
69
     * @param RouterInterface $router
70
     */
71 18
    public function __construct(
72
        EntityManagerInterface $em,
73
        EventDispatcherInterface $dispatcher,
74
        UserManagerInterface $userManager,
75
        TaskStackManagerInterface $taskStackManager,
76
        DynamicFormBuilder $dynamicFormBuilder,
77
        RouterInterface $router
78
    ) {
79 18
        $this->em = $em;
80 18
        $this->dispatcher = $dispatcher;
81 18
        $this->userManager = $userManager;
82 18
        $this->taskStackManager = $taskStackManager;
83 18
        $this->dynamicFormBuilder = $dynamicFormBuilder;
84 18
        $this->router = $router;
85 18
    }
86
87 4
    public function getDynamicFormData(PersonInterface $person, Request $request, $scope)
88
    {
89 4
        $nextTask = $this->taskStackManager->getNextTask();
90 4
        $redirectUrl = $request->get('redirect_url');
91 4
        if ($nextTask) {
92 3
            $redirectUrl = $this->taskStackManager->getTargetUrl($nextTask->getTarget());
93
        }
94 4
        if (!$redirectUrl) {
95 1
            $redirectUrl = $this->router->generate('lc_dashboard');
96
        }
97
98 4
        $placeOfBirth = new LocationSelectData();
99 4
        $placeOfBirth->getFromObject($person);
100
101 4
        $data = new DynamicFormData();
102 4
        $data->setPerson($person)
103 4
            ->setRedirectUrl($redirectUrl)
104 4
            ->setScope($scope)
105 4
            ->setPlaceOfBirth($placeOfBirth)
106 4
            ->setIdCardState($this->getStateFromRequest($request));
107
108 4
        $this->dispatchProfileEditInitialize($request, $person);
109
110 4
        return $data;
111
    }
112
113 1
    public function buildForm(FormInterface $form, DynamicFormData $data, array $scopes)
114
    {
115 1
        foreach ($scopes as $scope) {
116 1
            $this->dynamicFormBuilder->addFieldFromScope($form, $scope, $data);
117
        }
118 1
        $form->add('redirect_url', HiddenType::class)
119 1
            ->add('scope', HiddenType::class);
120
121 1
        return $form;
122
    }
123
124 3
    public function processForm(FormInterface $form, Request $request)
125
    {
126
        $dynamicFormResponse = [
127 3
            'response' => null,
128 3
            'form' => $form,
129
        ];
130 3
        $form->handleRequest($request);
131 3
        if (!$form->isValid()) {
132 1
            return $dynamicFormResponse;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $dynamicFormResponse returns the type array<string,Symfony\Com...orm\FormInterface|null> which is incompatible with the return type mandated by LoginCidadao\DynamicForm...nterface::processForm() of Symfony\Component\Form\FormInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
133
        }
134
135 2
        $this->dispatchFormEvent($form, $request, DynamicFormEvents::POST_FORM_VALIDATION);
136 2
        $event = null;
137 2
        if ($form->has('person')) {
138 1
            $event = $this->dispatchFormEvent($form->get('person'), $request, FOSUserEvents::PROFILE_EDIT_SUCCESS);
139
        }
140
141
        /** @var DynamicFormData $data */
142 2
        $data = $form->getData();
143 2
        $person = $data->getPerson();
144 2
        $address = $data->getAddress();
145 2
        $idCard = $data->getIdCard();
146 2
        $placeOfBirth = $data->getPlaceOfBirth();
147
148 2
        if ($placeOfBirth instanceof LocationSelectData) {
0 ignored issues
show
introduced by
$placeOfBirth is always a sub-type of LoginCidadao\CoreBundle\Model\LocationSelectData.
Loading history...
149 1
            $placeOfBirth->toObject($person);
150
        }
151
152 2
        $this->userManager->updateUser($person);
153
154 2
        if ($address instanceof PersonAddress) {
0 ignored issues
show
introduced by
$address is always a sub-type of LoginCidadao\CoreBundle\Entity\PersonAddress.
Loading history...
155 2
            $address->setPerson($person);
156 2
            $this->em->persist($address);
157
        }
158
159 2
        if ($idCard instanceof IdCardInterface) {
0 ignored issues
show
introduced by
$idCard is always a sub-type of LoginCidadao\CoreBundle\Model\IdCardInterface.
Loading history...
160 1
            $this->em->persist($idCard);
161
        }
162
163 2
        $currentTask = $this->taskStackManager->getCurrentTask();
164 2
        if ($currentTask instanceof CompleteUserInfoTask) {
165 2
            $this->taskStackManager->setTaskSkipped($currentTask);
166
        }
167
168 2
        $response = new RedirectResponse($data->getRedirectUrl());
169 2
        $response = $this->taskStackManager->processRequest($request, $response);
170 2
        if ($event && $response) {
171 1
            $event->setResponse($response);
172
        }
173 2
        $this->dispatchProfileEditCompleted($person, $request, $response);
174 2
        $this->em->flush();
175
176 2
        if ($form->has('person')) {
177 1
            $this->dispatcher->dispatch(DynamicFormEvents::POST_FORM_EDIT, $event);
178 1
            $this->dispatcher->dispatch(DynamicFormEvents::PRE_REDIRECT, $event);
179
        }
180
181 2
        $dynamicFormResponse['response'] = $response;
182 2
        if ($event) {
183 1
            $dynamicFormResponse['response'] = $event->getResponse();
184
        }
185
186 2
        return $dynamicFormResponse;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $dynamicFormResponse returns the type array<string,Symfony\Com...orm\FormInterface|null> which is incompatible with the return type mandated by LoginCidadao\DynamicForm...nterface::processForm() of Symfony\Component\Form\FormInterface.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
187
    }
188
189 3
    public function getClient($clientId)
190
    {
191 3
        $parsing = explode('_', $clientId, 2);
192 3
        if (count($parsing) !== 2) {
193 1
            throw new \InvalidArgumentException('Invalid client_id.');
194
        }
195
196 2
        $client = $this->em->getRepository('LoginCidadaoOAuthBundle:Client')
197 2
            ->findOneBy(['id' => $parsing[0], 'randomId' => $parsing[1]]);
198
199 2
        if (!$client instanceof ClientInterface) {
200 1
            throw new NotFoundHttpException('Client not found');
201
        }
202
203 1
        return $client;
204
    }
205
206 4
    private function dispatchProfileEditInitialize(Request $request, PersonInterface $person)
207
    {
208 4
        $event = new GetResponseUserEvent($person, $request);
209 4
        $this->dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_INITIALIZE, $event);
210
211 4
        return $event;
212
    }
213
214 2
    private function dispatchFormEvent(FormInterface $form, Request $request, $eventName)
215
    {
216 2
        $event = new FormEvent($form, $request);
217 2
        $this->dispatcher->dispatch($eventName, $event);
218
219 2
        return $event;
220
    }
221
222 2
    private function dispatchProfileEditCompleted(PersonInterface $person, Request $request, Response $response)
223
    {
224 2
        $event = new FilterUserResponseEvent($person, $request, $response);
225 2
        $this->dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_COMPLETED, $event);
226
227 2
        return $event;
228
    }
229
230
    /**
231
     * @param Request $request
232
     * @return State
233
     */
234 4
    private function getStateFromRequest(Request $request)
235
    {
236
        /** @var StateRepository $repo */
237 4
        $repo = $this->em->getRepository('LoginCidadaoCoreBundle:State');
238
239 4
        $stateId = $request->get('id_card_state_id', null);
240 4
        if ($stateId !== null) {
241
            /** @var State $state */
242 1
            $state = $repo->find($stateId);
243
244 1
            return $state;
245
        }
246
247 3
        $stateAcronym = $request->get('id_card_state', null);
248 3
        if ($stateAcronym !== null) {
249
            /** @var State $state */
250 1
            $state = $repo->findOneBy(['acronym' => $stateAcronym]);
251
252 1
            return $state;
253
        }
254
255 2
        return null;
256
    }
257
258 4
    public function getLocationDataFromRequest(Request $request)
259
    {
260 4
        $country = $this->getLocation($request, 'country');
261 4
        $state = $this->getLocation($request, 'state');
262 4
        $city = $this->getLocation($request, 'city');
263
264 4
        $locationData = new LocationSelectData();
265
266 4
        if ($city instanceof City) {
267 1
            $locationData->setCity($city)
268 1
                ->setState($city->getState())
269 1
                ->setCountry($city->getState()->getCountry());
270 3
        } elseif ($state instanceof State) {
271 1
            $locationData->setCity(null)
272 1
                ->setState($state)
273 1
                ->setCountry($state->getCountry());
274 2
        } elseif ($country instanceof Country) {
275 1
            $locationData->setCity(null)
276 1
                ->setState(null)
277 1
                ->setCountry($country);
278
        }
279
280 4
        $data = new DynamicFormData();
281 4
        $data->setPlaceOfBirth($locationData);
282
283 4
        return $data;
284
    }
285
286 3
    private function getLocationRepository($type)
287
    {
288 3
        $repo = null;
289
        switch ($type) {
290 3
            case 'city':
291 3
            case 'state':
292 3
            case 'country':
293 3
                $repo = $this->em->getRepository('LoginCidadaoCoreBundle:'.ucfirst($type));
294 3
                break;
295
        }
296
297 3
        return $repo;
298
    }
299
300 4
    private function getLocation(Request $request, $type)
301
    {
302 4
        $id = $request->get($type);
303 4
        if ($id === null) {
304 1
            return null;
305
        }
306 3
        $repo = $this->getLocationRepository($type);
307
308 3
        return $repo->find($id);
309
    }
310
311 1
    public function skipCurrent(Request $request, Response $defaultResponse)
312
    {
313 1
        $task = $this->taskStackManager->getCurrentTask();
314 1
        if ($task instanceof CompleteUserInfoTask) {
315 1
            $this->taskStackManager->setTaskSkipped($task);
316
        }
317
318 1
        return $this->taskStackManager->processRequest($request, $defaultResponse);
319
    }
320
321 2
    public function getSkipUrl(DynamicFormData $data)
322
    {
323 2
        $task = $this->taskStackManager->getCurrentTask();
324 2
        if ($task instanceof CompleteUserInfoTask) {
325 1
            return $this->router->generate('dynamic_form_skip');
326
        }
327
328 1
        return $data->getRedirectUrl();
329
    }
330
}
331