1 <?php 
declare(strict_types
=1); 
   4  * This file is part of the Rapsys UserBundle package. 
   6  * (c) Raphaël Gertz <symfony@rapsys.eu> 
   8  * For the full copyright and license information, please view the LICENSE 
   9  * file that was distributed with this source code. 
  12 namespace Rapsys\UserBundle\Controller
; 
  14 use Doctrine\DBAL\Exception\UniqueConstraintViolationException
; 
  15 use Symfony\Bridge\Twig\Mime\TemplatedEmail
; 
  16 use Symfony\Component\Form\FormError
; 
  17 use Symfony\Component\HttpFoundation\Request
; 
  18 use Symfony\Component\HttpFoundation\Response
; 
  19 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException
; 
  20 use Symfony\Component\Mailer\Exception\TransportExceptionInterface
; 
  21 use Symfony\Component\Mime\Address
; 
  22 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
; 
  23 use Symfony\Component\Security\Http\Authentication\AuthenticationUtils
; 
  28 class DefaultController 
extends AbstractController 
{ 
  30          * Confirm account from mail link 
  32          * @param Request $request The request 
  33          * @param string $hash The hashed password 
  34          * @param string $mail The shorted mail address 
  35          * @return Response The response 
  37         public function confirm(Request 
$request, string $hash, string $mail): Response 
{ 
  39                 if ($hash != $this->slugger
->hash($mail)) { 
  41                         throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); 
  45                 $mail = $this->slugger
->unshort($smail = $mail); 
  48                 if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) { 
  50                         //XXX: prevent slugger reverse engineering by not displaying decoded mail 
  51                         throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail])); 
  54                 //Without existing registrant 
  55                 if (!($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail))) { 
  56                         //Add error message mail already exists 
  57                         //XXX: prevent slugger reverse engineering by not displaying decoded mail 
  58                         $this->addFlash('error', $this->translator
->trans('Account %mail% do not exists', ['%mail%' => $smail])); 
  60                         //Redirect to register view 
  61                         return $this->redirectToRoute($this->config
['route']['register']['name'], ['mail' => $smail, 'field' => $sfield = $this->slugger
->serialize([]), 'hash' => $this->slugger
->hash($smail.$sfield)]+
$this->config
['route']['register']['context']); 
  65                 $user->setActive(true); 
  68                 $this->manager
->persist($user); 
  71                 $this->manager
->flush(); 
  73                 //Add error message mail already exists 
  74                 $this->addFlash('notice', $this->translator
->trans('Your account has been activated')); 
  76                 //Redirect to user view 
  77                 return $this->redirectToRoute($this->config
['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']); 
  81          * Edit account by shorted mail 
  83          * @param Request $request The request 
  84          * @param string $hash The hashed password 
  85          * @param string $mail The shorted mail address 
  86          * @return Response The response 
  88         public function edit(Request 
$request, string $hash, string $mail): Response 
{ 
  90                 if ($hash != $this->slugger
->hash($mail)) { 
  92                         throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); 
  96                 $mail = $this->slugger
->unshort($smail = $mail); 
  98                 //With existing subscriber 
  99                 if (empty($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail))) { 
 101                         //XXX: prevent slugger reverse engineering by not displaying decoded mail 
 102                         throw $this->createNotFoundException($this->translator
->trans('Unable to find account %mail%', ['%mail%' => $smail])); 
 105                 //Prevent access when not admin, user is not guest and not currently logged user 
 106                 if (!$this->isGranted('ROLE_ADMIN') && $user != $this->getUser() || !$this->isGranted('IS_AUTHENTICATED_FULLY')) { 
 107                         //Throw access denied 
 108                         //XXX: prevent slugger reverse engineering by not displaying decoded mail 
 109                         throw $this->createAccessDeniedException($this->translator
->trans('Unable to access user: %mail%', ['%mail%' => $smail])); 
 112                 //Create the RegisterType form and give the proper parameters 
 113                 $edit = $this->createForm($this->config
['edit']['view']['edit'], $user, [ 
 114                         //Set action to register route name and context 
 115                         'action' => $this->generateUrl($this->config
['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']), 
 117                         'civility_class' => $this->config
['class']['civility'], 
 118                         //Set civility default 
 119                         'civility_default' => $this->doctrine
->getRepository($this->config
['class']['civility'])->findOneByTitle($this->config
['default']['civility']), 
 121                         'mail' => $this->isGranted('ROLE_ADMIN'), 
 126                 ]+
$this->config
['edit']['field']); 
 129                 if ($this->isGranted('ROLE_ADMIN')) { 
 130                         //Create the LoginType form and give the proper parameters 
 131                         $reset = $this->createForm($this->config
['edit']['view']['reset'], $user, [ 
 132                                 //Set action to register route name and context 
 133                                 'action' => $this->generateUrl($this->config
['route']['edit']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']), 
 141                         if ($request->isMethod('POST')) { 
 142                                 //Refill the fields in case the form is not valid. 
 143                                 $reset->handleRequest($request); 
 145                                 //With reset submitted and valid 
 146                                 if ($reset->isSubmitted() && $reset->isValid()) { 
 148                                         $data = $reset->getData(); 
 151                                         $data->setPassword($this->hasher
->hashPassword($data, $data->getPassword())); 
 154                                         $this->manager
->persist($data); 
 156                                         //Flush to get the ids 
 157                                         $this->manager
->flush(); 
 160                                         $this->addFlash('notice', $this->translator
->trans('Account %mail% password updated', ['%mail%' => $mail = $data->getMail()])); 
 162                                         //Redirect to cleanup the form 
 163                                         return $this->redirectToRoute($this->config
['route']['edit']['name'], ['mail' => $smail = $this->slugger
->short($mail), 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']); 
 168                         $this->config
['edit']['view']['context']['reset'] = $reset->createView(); 
 172                 if ($request->isMethod('POST')) { 
 173                         //Refill the fields in case the form is not valid. 
 174                         $edit->handleRequest($request); 
 176                         //With edit submitted and valid 
 177                         if ($edit->isSubmitted() && $edit->isValid()) { 
 179                                 $data = $edit->getData(); 
 182                                 $this->manager
->persist($data); 
 184                                 //Try saving in database 
 186                                         //Flush to get the ids 
 187                                         $this->manager
->flush(); 
 190                                         $this->addFlash('notice', $this->translator
->trans('Account %mail% updated', ['%mail%' => $mail = $data->getMail()])); 
 192                                         //Redirect to cleanup the form 
 193                                         return $this->redirectToRoute($this->config
['route']['edit']['name'], ['mail' => $smail = $this->slugger
->short($mail), 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['edit']['context']); 
 194                                 //Catch double slug or mail 
 195                                 } catch (UniqueConstraintViolationException 
$e) { 
 196                                         //Add error message mail already exists 
 197                                         $this->addFlash('error', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $data->getMail()])); 
 201                 //XXX: prefer a reset on login to force user unspam action 
 202                 } elseif (!$this->isGranted('ROLE_ADMIN')) { 
 204                         $this->addFlash('notice', $this->translator
->trans('To change your password login with your mail and any password then follow the procedure')); 
 208                 return $this->render( 
 210                         $this->config
['edit']['view']['name'], 
 212                         ['edit' => $edit->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['edit']['view']['context'] 
 219          * @param Request $request The request 
 220          * @param AuthenticationUtils $authenticationUtils The authentication utils 
 221          * @param ?string $hash The hashed password 
 222          * @param ?string $mail The shorted mail address 
 223          * @return Response The response 
 225         public function login(Request 
$request, AuthenticationUtils 
$authenticationUtils, ?string $hash, ?string $mail): Response 
{ 
 226                 //Create the LoginType form and give the proper parameters 
 227                 $login = $this->createForm($this->config
['login']['view']['form'], null, [ 
 228                         //Set action to login route name and context 
 229                         'action' => $this->generateUrl($this->config
['route']['login']['name'], $this->config
['route']['login']['context']), 
 230                         //Disable repeated password 
 231                         'password_repeated' => false, 
 240                 if (!empty($mail) && !empty($hash)) { 
 242                         if ($hash != $this->slugger
->hash($mail)) { 
 244                                 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); 
 248                         $mail = $this->slugger
->unshort($smail = $mail); 
 251                         if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) { 
 253                                 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail])); 
 257                         $login->get('mail')->setData($mail); 
 258                 //Last username entered by the user 
 259                 } elseif ($lastUsername = $authenticationUtils->getLastUsername()) { 
 260                         $login->get('mail')->setData($lastUsername); 
 263                 //Get the login error if there is one 
 264                 if ($error = $authenticationUtils->getLastAuthenticationError()) { 
 265                         //Get translated error 
 266                         $error = $this->translator
->trans($error->getMessageKey()); 
 268                         //Add error message to mail field 
 269                         $login->get('mail')->addError(new FormError($error)); 
 271                         //Create the LoginType form and give the proper parameters 
 272                         $recover = $this->createForm($this->config
['recover']['view']['form'], null, [ 
 273                                 //Set action to recover route name and context 
 274                                 'action' => $this->generateUrl($this->config
['route']['recover']['name'], $this->config
['route']['recover']['context']), 
 281                         //Get recover mail entity 
 282                         $recover->get('mail') 
 283                                 //Set mail from login form 
 284                                 ->setData($login->get('mail')->getData()) 
 286                                 ->addError(new FormError($this->translator
->trans('Use this form to recover your account'))); 
 288                         //Add recover form to context 
 289                         $context['recover'] = $recover->createView(); 
 292                         $this->addFlash('notice', $this->translator
->trans('To change your password login with your mail and any password then follow the procedure')); 
 296                 return $this->render( 
 298                         $this->config
['login']['view']['name'], 
 300                         ['login' => $login->createView()]+
$context+
$this->config
['login']['view']['context'] 
 307          * @param Request $request The request 
 308          * @param ?string $hash The hashed password 
 309          * @param ?string $pass The shorted password 
 310          * @param ?string $mail The shorted mail address 
 311          * @return Response The response 
 313         public function recover(Request 
$request, ?string $hash, ?string $pass, ?string $mail): Response 
{ 
 314                 //Without mail, pass and hash 
 315                 if (empty($mail) && empty($pass) && empty($hash)) { 
 316                         //Create the LoginType form and give the proper parameters 
 317                         $form = $this->createForm($this->config
['recover']['view']['form'], null, [ 
 318                                 //Set action to recover route name and context 
 319                                 'action' => $this->generateUrl($this->config
['route']['recover']['name'], $this->config
['route']['recover']['context']), 
 327                         if ($request->isMethod('POST')) { 
 328                                 //Refill the fields in case the form is not valid. 
 329                                 $form->handleRequest($request); 
 331                                 //With form submitted and valid 
 332                                 if ($form->isSubmitted() && $form->isValid()) { 
 334                                         $data = $form->getData(); 
 336                                         //Find user by data mail 
 337                                         if ($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($data['mail'])) { 
 339                                                 $recoverMail =& $this->config
['recover']['mail']; 
 342                                                 $mail = $this->slugger
->short($user->getMail()); 
 345                                                 $pass = $this->slugger
->hash($user->getPassword()); 
 347                                                 //Generate each route route 
 348                                                 foreach($this->config
['recover']['route'] as $route => $tag) { 
 349                                                         //Only process defined routes 
 350                                                         if (!empty($this->config
['route'][$route])) { 
 351                                                                 //Process for recover mail url 
 352                                                                 if ($route == 'recover') { 
 353                                                                         //Set the url in context 
 354                                                                         $recoverMail['context'][$tag] = $this->router
->generate( 
 355                                                                                 $this->config
['route'][$route]['name'], 
 356                                                                                 //Prepend recover context with tag 
 360                                                                                         'hash' => $this->slugger
->hash($mail.$pass) 
 361                                                                                 ]+
$this->config
['route'][$route]['context'], 
 362                                                                                 UrlGeneratorInterface
::ABSOLUTE_URL
 
 369                                                 $recoverMail['context']['recipient_mail'] = $user->getMail(); 
 372                                                 $recoverMail['context']['recipient_name'] = $user->getRecipientName(); 
 374                                                 //Init subject context 
 375                                                 $subjectContext = $this->slugger
->flatten(array_replace_recursive($this->config
['recover']['view']['context'], $recoverMail['context']), null, '.', '%', '%'); 
 378                                                 $recoverMail['subject'] = ucfirst($this->translator
->trans($recoverMail['subject'], $subjectContext)); 
 381                                                 $message = (new TemplatedEmail()) 
 383                                                         ->from(new Address($this->config
['contact']['mail'], $this->config
['contact']['title'])) 
 385                                                         //XXX: remove the debug set in vendor/symfony/mime/Address.php +46 
 386                                                         ->to(new Address($recoverMail['context']['recipient_mail'], $recoverMail['context']['recipient_name'])) 
 388                                                         ->subject($recoverMail['subject']) 
 390                                                         //Set path to twig templates 
 391                                                         ->htmlTemplate($recoverMail['html']) 
 392                                                         ->textTemplate($recoverMail['text']) 
 395                                                         //XXX: require recursive merge to avoid loosing subkeys 
 396                                                         //['subject' => $recoverMail['subject']]+$recoverMail['context']+$this->config['recover']['view']['context'] 
 397                                                         ->context(array_replace_recursive($this->config
['recover']['view']['context'], $recoverMail['context'], ['subject' => $recoverMail['subject']])); 
 399                                                 //Try sending message 
 400                                                 //XXX: mail delivery may silently fail 
 403                                                         $this->mailer
->send($message); 
 405                                                         //Redirect on the same route with sent=1 to cleanup form 
 406                                                         return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params')); 
 407                                                 //Catch obvious transport exception 
 408                                                 } catch(TransportExceptionInterface 
$e) { 
 409                                                         //Add error message mail unreachable 
 410                                                         $form->get('mail')->addError(new FormError($this->translator
->trans('Account found but unable to contact: %mail%', array('%mail%' => $data['mail'])))); 
 414                                                 //Add error message to mail field 
 415                                                 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to find account %mail%', ['%mail%' => $data['mail']]))); 
 421                         return $this->render( 
 423                                 $this->config
['recover']['view']['name'], 
 425                                 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['recover']['view']['context'] 
 430                 if ($hash != $this->slugger
->hash($mail.$pass)) { 
 432                         throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); 
 436                 $mail = $this->slugger
->unshort($smail = $mail); 
 439                 if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) { 
 441                         //XXX: prevent slugger reverse engineering by not displaying decoded mail 
 442                         throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail])); 
 445                 //With existing subscriber 
 446                 if (empty($user = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail))) { 
 448                         //XXX: prevent slugger reverse engineering by not displaying decoded mail 
 449                         throw $this->createNotFoundException($this->translator
->trans('Unable to find account %mail%', ['%mail%' => $smail])); 
 452                 //With unmatched pass 
 453                 if ($pass != $this->slugger
->hash($user->getPassword())) { 
 455                         //XXX: prevent use of outdated recover link 
 456                         throw $this->createNotFoundException($this->translator
->trans('Outdated recover link')); 
 459                 //Create the LoginType form and give the proper parameters 
 460                 $form = $this->createForm($this->config
['recover']['view']['form'], $user, [ 
 461                         //Set action to recover route name and context 
 462                         'action' => $this->generateUrl($this->config
['route']['recover']['name'], ['mail' => $smail, 'pass' => $pass, 'hash' => $hash]+
$this->config
['route']['recover']['context']), 
 470                 if ($request->isMethod('POST')) { 
 471                         //Refill the fields in case the form is not valid. 
 472                         $form->handleRequest($request); 
 474                         //With form submitted and valid 
 475                         if ($form->isSubmitted() && $form->isValid()) { 
 477                                 $data = $form->getData(); 
 479                                 //Set hashed password 
 480                                 $hashed = $this->hasher
->hashPassword($user, $user->getPassword()); 
 483                                 $pass = $this->slugger
->hash($hashed); 
 486                                 $user->setPassword($hashed); 
 489                                 $this->manager
->persist($user); 
 492                                 $this->manager
->flush(); 
 495                                 $this->addFlash('notice', $this->translator
->trans('Account %mail% password updated', ['%mail%' => $mail])); 
 497                                 //Redirect to user login 
 498                                 return $this->redirectToRoute($this->config
['route']['login']['name'], ['mail' => $smail, 'hash' => $this->slugger
->hash($smail)]+
$this->config
['route']['login']['context']); 
 503                 return $this->render( 
 505                         $this->config
['recover']['view']['name'], 
 507                         ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['recover']['view']['context'] 
 512          * Register an account 
 514          * @param Request $request The request 
 515          * @param ?string $hash The hashed serialized field array 
 516          * @param ?string $field The serialized then shorted form field array 
 517          * @param ?string $mail The shorted mail address 
 518          * @return Response The response 
 520         public function register(Request 
$request, ?string $hash, ?string $field, ?string $mail): Response 
{ 
 522                 if (!empty($_POST['register']['mail'])) { 
 524                         $this->logger
->emergency( 
 525                                 $this->translator
->trans( 
 526                                         'register: mail=%mail% locale=%locale% confirm=%confirm%', 
 528                                                 '%mail%' => $postMail = $_POST['register']['mail'], 
 529                                                 '%locale%' => $request->getLocale(), 
 530                                                 '%confirm%' => $this->router
->generate( 
 531                                                         $this->config
['route']['confirm']['name'], 
 532                                                         //Prepend subscribe context with tag 
 534                                                                 'mail' => $postSmail = $this->slugger
->short($postMail), 
 535                                                                 'hash' => $this->slugger
->hash($postSmail) 
 536                                                         ]+
$this->config
['route']['confirm']['context'], 
 537                                                         UrlGeneratorInterface
::ABSOLUTE_URL
 
 544                 //With mail and field 
 545                 if (!empty($field) && !empty($hash)) { 
 547                         if ($hash != $this->slugger
->hash($mail.$field)) { 
 549                                 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'hash', '%value%' => $hash])); 
 555                                 $mail = $this->slugger
->unshort($smail = $mail); 
 558                                 if (filter_var($mail, FILTER_VALIDATE_EMAIL
) === false) { 
 560                                         //XXX: prevent slugger reverse engineering by not displaying decoded mail 
 561                                         throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'mail', '%value%' => $smail])); 
 564                                 //With existing registrant 
 565                                 if ($existing = $this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail)) { 
 566                                         //With disabled existing 
 567                                         if ($existing->isDisabled()) { 
 569                                                 $response = $this->render( 
 571                                                         $this->config
['register']['view']['name'], 
 573                                                         ['title' => $this->translator
->trans('Access denied'), 'disabled' => 1]+
$this->config
['register']['view']['context'] 
 577                                                 $response->setStatusCode(403); 
 581                                         //With unactivated existing 
 582                                         } elseif (!$existing->isActivated()) { 
 584                                                 $activateMail =& $this->config
['register']['mail']; 
 586                                                 //Generate each route route 
 587                                                 foreach($this->config
['register']['route'] as $route => $tag) { 
 588                                                         //Only process defined routes 
 589                                                         if (!empty($this->config
['route'][$route])) { 
 590                                                                 //Process for confirm url 
 591                                                                 if ($route == 'confirm') { 
 592                                                                         //Set the url in context 
 593                                                                         $activateMail['context'][$tag] = $this->router
->generate( 
 594                                                                                 $this->config
['route'][$route]['name'], 
 595                                                                                 //Prepend subscribe context with tag 
 597                                                                                         'mail' => $smail = $this->slugger
->short($existing->getMail()), 
 598                                                                                         'hash' => $this->slugger
->hash($smail) 
 599                                                                                 ]+
$this->config
['route'][$route]['context'], 
 600                                                                                 UrlGeneratorInterface
::ABSOLUTE_URL
 
 607                                                 $activateMail['context']['recipient_mail'] = $existing->getMail(); 
 610                                                 $activateMail['context']['recipient_name'] = $existing->getRecipientName(); 
 612                                                 //Init subject context 
 613                                                 $subjectContext = $this->slugger
->flatten(array_replace_recursive($this->config
['register']['view']['context'], $activateMail['context']), null, '.', '%', '%'); 
 616                                                 $activateMail['subject'] = ucfirst($this->translator
->trans($activateMail['subject'], $subjectContext)); 
 619                                                 $message = (new TemplatedEmail()) 
 621                                                         ->from(new Address($this->config
['contact']['mail'], $this->config
['contact']['title'])) 
 623                                                         //XXX: remove the debug set in vendor/symfony/mime/Address.php +46 
 624                                                         ->to(new Address($activateMail['context']['recipient_mail'], $activateMail['context']['recipient_name'])) 
 626                                                         ->subject($activateMail['subject']) 
 628                                                         //Set path to twig templates 
 629                                                         ->htmlTemplate($activateMail['html']) 
 630                                                         ->textTemplate($activateMail['text']) 
 633                                                         ->context(['subject' => $activateMail['subject']]+
$activateMail['context']); 
 635                                                 //Try sending message 
 636                                                 //XXX: mail delivery may silently fail 
 639                                                         $this->mailer
->send($message); 
 640                                                 //Catch obvious transport exception 
 641                                                 } catch(TransportExceptionInterface 
$e) { 
 642                                                         //Add error message mail unreachable 
 643                                                         $this->addFlash('error', $this->translator
->trans('Account %mail% tried activate but unable to contact', ['%mail%' => $existing->getMail()])); 
 647                                                 $routeParams = $request->get('_route_params'); 
 649                                                 //Remove mail, field and hash from route params 
 650                                                 unset($routeParams['mail'], $routeParams['field'], $routeParams['hash']); 
 652                                                 //Redirect on the same route with sent=1 to cleanup form 
 653                                                 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$routeParams); 
 656                                         //Add error message mail already exists 
 657                                         $this->addFlash('warning', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $existing->getMail()])); 
 659                                         //Redirect to user view 
 660                                         return $this->redirectToRoute( 
 661                                                 $this->config
['route']['edit']['name'], 
 663                                                         'mail' => $smail = $this->slugger
->short($existing->getMail()), 
 664                                                         'hash' => $this->slugger
->hash($smail) 
 665                                                 ]+
$this->config
['route']['edit']['context'] 
 676                                 //Unshort then unserialize field 
 677                                 $field = $this->slugger
->unserialize($sfield = $field); 
 679                         } catch (\Error
|\Exception 
$e) { 
 681                                 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'field', '%value%' => $field]), $e); 
 684                         //With non array field 
 685                         if (!is_array($field)) { 
 687                                 throw new BadRequestHttpException($this->translator
->trans('Invalid %field% field: %value%', ['%field%' => 'field', '%value%' => $field])); 
 689                 //Without field and hash 
 702                 $reflection = new \
ReflectionClass($this->config
['class']['user']); 
 705                 $user = $reflection->newInstance(strval($mail)); 
 707                 //Create the RegisterType form and give the proper parameters 
 708                 $form = $this->createForm($this->config
['register']['view']['form'], $user, $field+
[ 
 709                         //Set action to register route name and context 
 710                         'action' => $this->generateUrl($this->config
['route']['register']['name'], ['mail' => $smail, 'field' => $sfield, 'hash' => $hash]+
$this->config
['route']['register']['context']), 
 712                         'civility_class' => $this->config
['class']['civility'], 
 713                         //Set civility default 
 714                         'civility_default' => $this->doctrine
->getRepository($this->config
['class']['civility'])->findOneByTitle($this->config
['default']['civility']), 
 719                 ]+
$this->config
['register']['field']); 
 722                 if ($request->isMethod('POST')) { 
 723                         //Refill the fields in case the form is not valid. 
 724                         $form->handleRequest($request); 
 726                         //With form submitted and valid 
 727                         if ($form->isSubmitted() && $form->isValid()) { 
 729                                 $data = $form->getData(); 
 731                                 //With existing registrant 
 732                                 if ($this->doctrine
->getRepository($this->config
['class']['user'])->findOneByMail($mail = $data->getMail())) { 
 733                                         //Add error message mail already exists 
 734                                         $this->addFlash('warning', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $mail])); 
 736                                         //Redirect to user view 
 737                                         return $this->redirectToRoute( 
 738                                                 $this->config
['route']['edit']['name'], 
 740                                                         'mail' => $smail = $this->slugger
->short($mail), 
 741                                                         'hash' => $this->slugger
->hash($smail) 
 742                                                 ]+
$this->config
['route']['edit']['context'] 
 747                                 $registerMail =& $this->config
['register']['mail']; 
 750                                 $user->setPassword($this->hasher
->hashPassword($user, $user->getPassword())); 
 753                                 $this->manager
->persist($user); 
 755                                 //Iterate on default group 
 756                                 foreach($this->config
['default']['group'] as $i => $groupTitle) { 
 758                                         if (($group = $this->doctrine
->getRepository($this->config
['class']['group'])->findOneByTitle($groupTitle))) { 
 760                                                 //XXX: see vendor/symfony/security-core/Role/Role.php 
 761                                                 $user->addGroup($group); 
 765                                                 //XXX: consider missing group as fatal 
 766                                                 throw new \
Exception(sprintf('Group from rapsys_user.default.group[%d] not found by title: %s', $i, $groupTitle)); 
 770                                 //Generate each route route 
 771                                 foreach($this->config
['register']['route'] as $route => $tag) { 
 772                                         //Only process defined routes 
 773                                         if (!empty($this->config
['route'][$route])) { 
 774                                                 //Process for confirm url 
 775                                                 if ($route == 'confirm') { 
 776                                                         //Set the url in context 
 777                                                         $registerMail['context'][$tag] = $this->router
->generate( 
 778                                                                 $this->config
['route'][$route]['name'], 
 779                                                                 //Prepend subscribe context with tag 
 781                                                                         'mail' => $smail = $this->slugger
->short($data->getMail()), 
 782                                                                         'hash' => $this->slugger
->hash($smail) 
 783                                                                 ]+
$this->config
['route'][$route]['context'], 
 784                                                                 UrlGeneratorInterface
::ABSOLUTE_URL
 
 791                                 $registerMail['context']['recipient_mail'] = $data->getMail(); 
 794                                 $registerMail['context']['recipient_name'] = $data->getRecipientName(); 
 796                                 //Init subject context 
 797                                 $subjectContext = $this->slugger
->flatten(array_replace_recursive($this->config
['register']['view']['context'], $registerMail['context']), null, '.', '%', '%'); 
 800                                 $registerMail['subject'] = ucfirst($this->translator
->trans($registerMail['subject'], $subjectContext)); 
 803                                 $message = (new TemplatedEmail()) 
 805                                         ->from(new Address($this->config
['contact']['mail'], $this->config
['contact']['title'])) 
 807                                         //XXX: remove the debug set in vendor/symfony/mime/Address.php +46 
 808                                         ->to(new Address($registerMail['context']['recipient_mail'], $registerMail['context']['recipient_name'])) 
 810                                         ->subject($registerMail['subject']) 
 812                                         //Set path to twig templates 
 813                                         ->htmlTemplate($registerMail['html']) 
 814                                         ->textTemplate($registerMail['text']) 
 817                                         ->context(['subject' => $registerMail['subject']]+
$registerMail['context']); 
 819                                 //Try saving in database 
 822                                         $this->manager
->flush(); 
 824                                         //Add error message mail already exists 
 825                                         $this->addFlash('notice', $this->translator
->trans('Your account has been created')); 
 827                                         //Try sending message 
 828                                         //XXX: mail delivery may silently fail 
 831                                                 $this->mailer
->send($message); 
 833                                                 //Redirect on the same route with sent=1 to cleanup form 
 834                                                 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params')); 
 835                                         //Catch obvious transport exception 
 836                                         } catch(TransportExceptionInterface 
$e) { 
 837                                                 //Add error message mail unreachable 
 838                                                 $form->get('mail')->addError(new FormError($this->translator
->trans('Account %mail% tried subscribe but unable to contact', ['%mail%' => $data->getMail()]))); 
 840                                 //Catch double subscription 
 841                                 } catch (UniqueConstraintViolationException 
$e) { 
 842                                         //Add error message mail already exists 
 843                                         $this->addFlash('error', $this->translator
->trans('Account %mail% already exists', ['%mail%' => $mail])); 
 849                 return $this->render( 
 851                         $this->config
['register']['view']['name'], 
 853                         ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['register']['view']['context']