Failed Conditions
Branch master (116909)
by Guilherme
08:28
created

Nfg::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 32
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 15
nc 1
nop 15
dl 0
loc 32
ccs 0
cts 16
cp 0
crap 2
rs 8.8571
c 0
b 0
f 0

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
 * 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 PROCERGS\LoginCidadao\NfgBundle\Service;
12
13
use Doctrine\ORM\EntityManager;
14
use FOS\UserBundle\Model\UserManagerInterface;
15
use FOS\UserBundle\Event\FilterUserResponseEvent;
16
use FOS\UserBundle\Event\FormEvent;
17
use FOS\UserBundle\Event\GetResponseUserEvent;
18
use FOS\UserBundle\Form\Factory\FormFactory;
19
use FOS\UserBundle\FOSUserEvents;
20
use FOS\UserBundle\Security\LoginManagerInterface;
21
use FOS\UserBundle\Util\CanonicalizerInterface;
22
use LoginCidadao\CoreBundle\Model\PersonInterface;
23
use PROCERGS\LoginCidadao\NfgBundle\Entity\NfgProfile;
24
use PROCERGS\LoginCidadao\CoreBundle\Entity\PersonMeuRS;
25
use PROCERGS\LoginCidadao\CoreBundle\Helper\MeuRSHelper;
26
use PROCERGS\LoginCidadao\NfgBundle\Entity\NfgProfileRepository;
27
use PROCERGS\LoginCidadao\NfgBundle\Event\GetConnectCallbackResponseEvent;
28
use PROCERGS\LoginCidadao\NfgBundle\Event\GetDisconnectCallbackResponseEvent;
29
use PROCERGS\LoginCidadao\NfgBundle\Event\GetLoginCallbackResponseEvent;
30
use PROCERGS\LoginCidadao\NfgBundle\Exception\ConnectionNotFoundException;
31
use PROCERGS\LoginCidadao\NfgBundle\Exception\CpfInUseException;
32
use PROCERGS\LoginCidadao\NfgBundle\Exception\CpfMismatchException;
33
use PROCERGS\LoginCidadao\NfgBundle\Exception\EmailInUseException;
34
use PROCERGS\LoginCidadao\NfgBundle\Exception\MissingRequiredInformationException;
35
use PROCERGS\LoginCidadao\NfgBundle\Exception\NfgAccountCollisionException;
36
use PROCERGS\LoginCidadao\NfgBundle\Exception\NfgServiceUnavailableException;
37
use PROCERGS\LoginCidadao\NfgBundle\Exception\OverrideResponseException;
38
use PROCERGS\LoginCidadao\NfgBundle\Helper\UrlHelper;
39
use PROCERGS\LoginCidadao\NfgBundle\Mailer\MailerInterface;
40
use PROCERGS\LoginCidadao\NfgBundle\NfgEvents;
41
use PROCERGS\LoginCidadao\NfgBundle\Traits\CircuitBreakerAwareTrait;
42
use Psr\Log\LoggerAwareInterface;
43
use Psr\Log\LoggerInterface;
44
use Ramsey\Uuid\Uuid;
45
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
46
use Symfony\Component\HttpFoundation\JsonResponse;
47
use Symfony\Component\HttpFoundation\RedirectResponse;
48
use Symfony\Component\HttpFoundation\Request;
49
use Symfony\Component\HttpFoundation\Response;
50
use Symfony\Component\HttpFoundation\Session\SessionInterface;
51
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
52
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
53
use Symfony\Component\Routing\RouterInterface;
54
use Symfony\Component\Security\Core\Exception\AccountStatusException;
55
56
class Nfg implements LoggerAwareInterface
57
{
58
    use CircuitBreakerAwareTrait {
59
        reportSuccess as traitReportSuccess;
60
        reportFailure as traitReportFailure;
61
    }
62
63
    /**
64
     * Key used to store the NFG AccessID in session
65
     */
66
    const ACCESS_ID_SESSION_KEY = 'nfg.access_id';
67
68
    /** @var EntityManager */
69
    private $em;
70
71
    /** @var NfgSoapInterface */
72
    private $nfgSoap;
73
74
    /** @var RouterInterface */
75
    private $router;
76
77
    /** @var SessionInterface */
78
    private $session;
79
80
    /** @var LoginManagerInterface */
81
    private $loginManager;
82
83
    /** @var MeuRSHelper */
84
    private $meuRSHelper;
85
86
    /** @var LoggerInterface */
87
    private $logger;
88
89
    /** @var string */
90
    private $loginEndpoint;
91
92
    /** @var string */
93
    private $authorizationEndpoint;
94
95
    /** @var string */
96
    private $firewallName;
97
98
    /** @var UserManagerInterface */
99
    private $userManager;
100
101
    /** @var EventDispatcherInterface */
102
    private $dispatcher;
103
104
    /** @var FormFactory */
105
    private $formFactory;
106
107
    /** @var NfgProfileRepository */
108
    private $nfgProfileRepository;
109
110
    /** @var MailerInterface */
111
    private $mailer;
112
113
    /** @var CanonicalizerInterface */
114
    private $emailCanonicalizer;
115
116
    public function __construct(
117
        EntityManager $em,
118
        NfgSoapInterface $client,
119
        RouterInterface $router,
120
        SessionInterface $session,
121
        LoginManagerInterface $loginManager,
122
        MeuRSHelper $meuRSHelper,
123
        EventDispatcherInterface $dispatcher,
124
        UserManagerInterface $userManager,
125
        FormFactory $formFactory,
126
        NfgProfileRepository $nfgProfileRepository,
127
        MailerInterface $mailer,
128
        CanonicalizerInterface $emailCanonicalizer,
129
        $firewallName,
130
        $loginEndpoint,
131
        $authorizationEndpoint
132
    ) {
133
        $this->em = $em;
134
        $this->nfgSoap = $client;
135
        $this->router = $router;
136
        $this->session = $session;
137
        $this->loginManager = $loginManager;
138
        $this->meuRSHelper = $meuRSHelper;
139
        $this->dispatcher = $dispatcher;
140
        $this->userManager = $userManager;
141
        $this->formFactory = $formFactory;
142
        $this->nfgProfileRepository = $nfgProfileRepository;
143
        $this->mailer = $mailer;
144
        $this->emailCanonicalizer = $emailCanonicalizer;
145
        $this->firewallName = $firewallName;
146
        $this->loginEndpoint = $loginEndpoint;
147
        $this->authorizationEndpoint = $authorizationEndpoint;
148
    }
149
150
    /**
151
     * @return string
152
     * @throws NfgServiceUnavailableException
153
     */
154
    private function getAccessId()
155
    {
156
        $nfgSoap = $this->nfgSoap;
157
158
        return $this->protect(function () use ($nfgSoap) {
159
            try {
160
                $accessId = $nfgSoap->getAccessID();
161
162
                return $accessId;
163
            } catch (NfgServiceUnavailableException $e) {
164
                throw $e;
165
            } catch (\Exception $e) {
166
                throw new NfgServiceUnavailableException($e->getMessage(), 500, $e);
167
            }
168
        });
169
    }
170
171
    /**
172
     * @param string $accessToken
173
     * @param string|null $voterRegistration
174
     * @param bool $testRequiredInfo
175
     * @return NfgProfile
176
     */
177
    public function getUserInfo($accessToken, $voterRegistration = null, $testRequiredInfo = true)
178
    {
179
        $nfgSoap = $this->nfgSoap;
180
181
        try {
182
            $nfgProfile = $this->protect(function () use ($nfgSoap, $accessToken, $voterRegistration) {
0 ignored issues
show
Unused Code introduced by
The import $nfgSoap is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
183
                return $this->nfgSoap->getUserInfo($accessToken, $voterRegistration);
184
            });
185
        } catch (NfgServiceUnavailableException $e) {
186
            throw $e;
187
        } catch (\Exception $e) {
188
            throw new NfgServiceUnavailableException($e->getMessage(), 500, $e);
189
        }
190
191
        $requiredInfo = [$nfgProfile->getName(), $nfgProfile->getCpf(), $nfgProfile->getEmail()];
192
        $missingRequiredInfo = array_search(null, $requiredInfo);
193
194
        if ($testRequiredInfo && false !== $missingRequiredInfo) {
195
            throw new MissingRequiredInformationException('Some needed information was not authorized on NFG.');
196
        }
197
198
        return $nfgProfile;
199
    }
200
201
    /**
202
     * @return JsonResponse
203
     */
204
    public function login()
205
    {
206
        return $this->redirect($this->loginEndpoint, 'nfg_login_callback');
207
    }
208
209
    public function loginCallback(array $params, $secret)
210
    {
211
        $cpf = array_key_exists('cpf', $params) ? $params['cpf'] : null;
212
        $accessId = array_key_exists('accessId', $params) ? $params['accessId'] : null;
213
        $prsec = array_key_exists('prsec', $params) ? $params['prsec'] : null;
214
215
        if (!$cpf || !$accessId || !$prsec) {
216
            throw new BadRequestHttpException('Missing CPF, AccessID or PRSEC');
217
        }
218
219
        $signature = hash_hmac('sha256', "$cpf$accessId", $secret);
220
        if (!$signature || strcmp(strtolower($signature), strtolower($prsec)) !== 0) {
221
            throw new AccessDeniedHttpException('Invalid PRSEC signature.');
222
        }
223
224
        if ($this->session->get(self::ACCESS_ID_SESSION_KEY) !== $accessId) {
225
            throw new AccessDeniedHttpException('Invalid AccessID');
226
        }
227
228
        /** @var PersonInterface $user */
229
        $personMeuRS = $this->meuRSHelper->getPersonByCpf($this->sanitizeCpf($cpf), true);
230
231
        if (!$personMeuRS || !$personMeuRS->getPerson() || !$personMeuRS->getNfgAccessToken()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $personMeuRS->getNfgAccessToken() of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
232
            throw new ConnectionNotFoundException('No user found matching this CPF');
233
        }
234
        $user = $personMeuRS->getPerson();
235
236
        return $this->logInUser($user, $params);
237
    }
238
239
    public function connect()
240
    {
241
        return $this->redirect($this->authorizationEndpoint, 'nfg_connect_callback');
242
    }
243
244
    /**
245
     * @param Request $request
246
     * @param PersonMeuRS $personMeuRS
247
     * @param bool $overrideExisting
248
     * @return Response
249
     */
250
    public function connectCallback(Request $request, PersonMeuRS $personMeuRS, $overrideExisting = false)
251
    {
252
        $response = null;
253
        $accessToken = $request->get('paccessid');
254
        if (!$accessToken) {
255
            throw new BadRequestHttpException("Missing paccessid parameter");
256
        }
257
258
        $nfgProfile = $this->getUserInfo($accessToken, $personMeuRS->getVoterRegistration());
259
260
        if (!($personMeuRS->getPerson() instanceof PersonInterface)) {
0 ignored issues
show
introduced by
The condition ! $personMeuRS->getPerso...e\Model\PersonInterface can never be true.
Loading history...
261
            try {
262
                $response = $this->register($request, $personMeuRS, $nfgProfile);
263
            } catch (OverrideResponseException $e) {
264
                $event = new GetConnectCallbackResponseEvent(
265
                    $request, $personMeuRS, $overrideExisting, $e->getResponse()
266
                );
267
                $this->dispatcher->dispatch(NfgEvents::CONNECT_CALLBACK_RESPONSE, $event);
268
269
                return $event->getResponse();
270
            }
271
        }
272
273
        $sanitizedCpf = $this->sanitizeCpf($nfgProfile->getCpf());
274
        if (!$personMeuRS->getPerson()->getCpf()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $personMeuRS->getPerson()->getCpf() of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
275
            $personMeuRS->getPerson()->setCpf($sanitizedCpf);
276
        }
277
278
        try {
279
            $this->checkCpf($personMeuRS, $nfgProfile, $overrideExisting);
280
        } catch (NfgAccountCollisionException $e) {
281
            $e->setAccessToken($accessToken);
282
            throw $e;
283
        }
284
285
        $nfgProfile = $this->syncNfgProfile($nfgProfile);
286
287
        $this->em->persist($nfgProfile);
288
        $personMeuRS->setNfgProfile($nfgProfile);
289
        $personMeuRS->setNfgAccessToken($accessToken);
290
        $this->em->flush();
291
292
        if (!$response) {
293
            $response = new RedirectResponse($this->router->generate('fos_user_profile_edit'));
294
        }
295
296
        $event = new GetConnectCallbackResponseEvent($request, $personMeuRS, $overrideExisting, $response);
297
        $this->dispatcher->dispatch(NfgEvents::CONNECT_CALLBACK_RESPONSE, $event);
298
299
        return $event->getResponse();
300
    }
301
302
    /**
303
     * @param PersonMeuRS $personMeuRS
304
     * @return Response
305
     */
306
    public function disconnect(PersonMeuRS $personMeuRS)
307
    {
308
        if ($personMeuRS->getNfgProfile()) {
309
            $this->em->remove($personMeuRS->getNfgProfile());
310
            $personMeuRS->setNfgAccessToken(null);
311
            $personMeuRS->setNfgProfile(null);
312
            $this->em->flush();
313
        }
314
315
        $response = new RedirectResponse($this->router->generate('fos_user_profile_edit'));
316
        $event = new GetDisconnectCallbackResponseEvent($personMeuRS, $response);
317
        $this->dispatcher->dispatch(NfgEvents::DISCONNECT_CALLBACK_RESPONSE, $event);
318
319
        return $event->getResponse();
320
    }
321
322
    private function redirect($endpoint, $callbackRoute)
323
    {
324
        $accessId = $this->getAccessId();
325
        $this->session->set(self::ACCESS_ID_SESSION_KEY, $accessId);
326
        $callbackUrl = $this->router->generate($callbackRoute, [], RouterInterface::ABSOLUTE_URL);
327
328
        $url = parse_url($endpoint);
329
        $url['query'] = UrlHelper::addToQuery(
330
            [
331
                'accessid' => $accessId,
332
                'urlretorno' => $callbackUrl,
333
            ],
334
            isset($url['query']) ? $url['query'] : null
335
        );
336
337
        return new JsonResponse(['target' => http_build_url($url)]);
338
    }
339
340
    /**
341
     * Sets a logger instance on the object.
342
     *
343
     * @param LoggerInterface $logger
344
     *
345
     * @return void
346
     */
347
    public function setLogger(LoggerInterface $logger)
348
    {
349
        $this->logger = $logger;
350
    }
351
352
    private function sanitizeCpf($cpf)
353
    {
354
        return str_pad(preg_replace('/[^0-9]/', '', $cpf), 11, '0', STR_PAD_LEFT);
355
    }
356
357
    /**
358
     * @param PersonMeuRS $personMeuRS
359
     * @param NfgProfile $nfgProfile
360
     * @param bool $overrideExisting
361
     */
362
    private function checkCpf(PersonMeuRS $personMeuRS, NfgProfile $nfgProfile, $overrideExisting = false)
363
    {
364
        $person = $personMeuRS->getPerson();
365
366
        // Check data inconsistency
367
        if ($person->getCpf() !== $this->sanitizeCpf($nfgProfile->getCpf())) {
368
            throw new CpfMismatchException("User's CPF doesn't match CPF from NFG.");
369
        }
370
371
        // Check CPF collision
372
        $otherPerson = $this->meuRSHelper->getPersonByCpf($person->getCpf(), true);
373
        if (null === $otherPerson || $otherPerson->getId() === $personMeuRS->getId()) {
374
            // No collision found. We're good! :)
375
            return;
376
        }
377
378
        if (!$otherPerson->getNfgProfile()) {
379
            // The other person isn't linked with NFG, so $person can safely get the CPF
380
            $otherPerson->getPerson()->setCpf(null);
381
            $this->em->persist($otherPerson->getPerson());
382
            $this->em->flush($otherPerson->getPerson());
383
384
            $this->mailer->notifyCpfLost($otherPerson->getPerson());
385
386
            return;
387
        }
388
389
        // Both users are linked to the same NFG account
390
        // What should we do?
391
        if (false === $overrideExisting) {
392
            throw new NfgAccountCollisionException();
393
        }
394
        // The user's choice was to remove the previous connection and use this new one
395
        $otherPerson->getPerson()->setCpf(null);
396
        $this->em->persist($otherPerson->getPerson());
397
        $this->em->flush($otherPerson->getPerson());
398
        $this->disconnect($otherPerson);
399
        $this->mailer->notifyConnectionTransferred($otherPerson->getPerson());
400
    }
401
402
    /**
403
     * @param Request $request
404
     * @param PersonMeuRS $personMeuRS
405
     * @param NfgProfile $nfgProfile
406
     * @return null|RedirectResponse|Response
407
     * @throws OverrideResponseException
408
     */
409
    private function register(Request $request, PersonMeuRS $personMeuRS, NfgProfile $nfgProfile)
410
    {
411
        $email = $this->emailCanonicalizer->canonicalize($nfgProfile->getEmail());
412
        if ($this->meuRSHelper->getPersonByEmail($email, true) !== null) {
413
            throw new EmailInUseException();
414
        }
415
416
        $sanitizedCpf = $this->sanitizeCpf($nfgProfile->getCpf());
417
        $otherPersonMeuRS = $this->meuRSHelper->getPersonByCpf($sanitizedCpf, true);
418
419
        if ($otherPersonMeuRS !== null) {
420
            if ($otherPersonMeuRS->getNfgProfile()) {
421
                $otherPersonNfgCpf = $otherPersonMeuRS->getNfgProfile()->getCpf();
422
            } else {
423
                $otherPersonNfgCpf = null;
424
            }
425
            if ($otherPersonMeuRS->getNfgAccessToken() && $otherPersonNfgCpf == $sanitizedCpf) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $otherPersonMeuRS->getNfgAccessToken() of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
426
                $response = $this->logInUser($otherPersonMeuRS->getPerson());
427
                throw new OverrideResponseException($response);
428
            }
429
            $this->handleCpfCollision($otherPersonMeuRS);
430
        }
431
432
        $names = explode(' ', $nfgProfile->getName());
433
434
        /** @var PersonInterface $user */
435
        $user = $this->userManager->createUser();
436
        $user->setUsername(Uuid::uuid4()->toString());
437
        $user
438
            ->setFirstName(array_shift($names))
439
            ->setSurname(implode(' ', $names))
440
            ->setEmail($nfgProfile->getEmail())
441
            ->setCpf($sanitizedCpf)
442
            ->setBirthdate($nfgProfile->getBirthdate())
443
            ->setMobile($nfgProfile->getMobile())
444
            ->setPassword('')
445
            ->setEnabled(true);
446
447
        $event = new GetResponseUserEvent($user, $request);
448
        $this->dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);
449
450
        if (null !== $event->getResponse()) {
451
            throw new OverrideResponseException($event->getResponse());
452
        }
453
454
        $form = $this->formFactory->createForm();
455
        $form->setData($user);
456
457
        $event = new FormEvent($form, $request);
458
        $this->dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);
459
460
        $this->userManager->updateUser($user);
461
462
        $nfgProfile = $this->syncNfgProfile($nfgProfile);
463
        $personMeuRS->setPerson($user);
464
        $personMeuRS->setNfgProfile($nfgProfile);
465
        $this->em->persist($personMeuRS);
466
        $this->em->persist($nfgProfile);
467
        $this->em->flush();
468
469
        if (null === $response = $event->getResponse()) {
0 ignored issues
show
introduced by
The condition null === $response = $event->getResponse() can never be false.
Loading history...
470
            $url = $this->router->generate('fos_user_registration_confirmed');
471
            $response = new RedirectResponse($url);
472
        }
473
474
        $this->dispatcher->dispatch(
475
            FOSUserEvents::REGISTRATION_COMPLETED,
476
            new FilterUserResponseEvent($user, $request, $response)
477
        );
478
479
        return $response;
480
    }
481
482
    /**
483
     * @param NfgProfile $latestNfgProfile
484
     * @return NfgProfile
485
     */
486
    public function syncNfgProfile(NfgProfile $latestNfgProfile)
487
    {
488
        $existingNfgProfile = $this->nfgProfileRepository->findByCpf($latestNfgProfile->getCpf());
489
490
        if ($existingNfgProfile instanceof NfgProfile) {
491
            $existingNfgProfile
492
                ->setName($latestNfgProfile->getName())
493
                ->setEmail($latestNfgProfile->getEmail())
494
                ->setBirthdate($latestNfgProfile->getBirthdate())
495
                ->setMobile($latestNfgProfile->getMobile())
496
                ->setAccessLvl($latestNfgProfile->getAccessLvl())
497
                ->setVoterRegistration($latestNfgProfile->getVoterRegistration())
498
                ->setVoterRegistrationSit($latestNfgProfile->getVoterRegistrationSit());
499
500
            return $existingNfgProfile;
501
        } else {
502
            return $latestNfgProfile;
503
        }
504
    }
505
506
    private function logInUser(PersonInterface $user, array $params = [])
507
    {
508
        $response = new RedirectResponse($this->router->generate('lc_home'));
509
510
        try {
511
            $this->loginManager->logInUser($this->firewallName, $user, $response);
512
        } catch (AccountStatusException $e) {
513
            // User account is disabled or something like that
514
            throw $e;
515
        }
516
517
        $event = new GetLoginCallbackResponseEvent($params, $response);
518
        $this->dispatcher->dispatch(NfgEvents::LOGIN_CALLBACK_RESPONSE, $event);
519
520
        return $event->getResponse();
521
    }
522
523
    private function handleCpfCollision(PersonMeuRS $otherPersonMeuRS)
524
    {
525
        if (!$otherPersonMeuRS->getNfgAccessToken()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $otherPersonMeuRS->getNfgAccessToken() of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
526
            $otherPersonMeuRS->getPerson()->setCpf(null);
527
            $this->mailer->notifyCpfLost($otherPersonMeuRS->getPerson());
528
            $this->em->persist($otherPersonMeuRS->getPerson());
529
            $this->em->flush($otherPersonMeuRS->getPerson());
530
        } else {
531
            throw new CpfInUseException();
532
        }
533
    }
534
}
535