3 namespace Rapsys\UserBundle\Controller
;
5 use Rapsys\UserBundle\Utils\Slugger
;
6 use Symfony\Bridge\Twig\Mime\TemplatedEmail
;
7 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController
;
8 use Symfony\Component\DependencyInjection\ContainerInterface
;
9 use Symfony\Component\Form\FormError
;
10 use Symfony\Component\HttpFoundation\Request
;
11 use Symfony\Component\Mailer\Exception\TransportExceptionInterface
;
12 use Symfony\Component\Mailer\MailerInterface
;
13 use Symfony\Component\Mime\NamedAddress
;
14 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
;
15 use Symfony\Component\Routing\RouterInterface
;
16 use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface
;
17 use Symfony\Component\Security\Http\Authentication\AuthenticationUtils
;
18 use Symfony\Component\Translation\TranslatorInterface
;
20 class DefaultController
extends AbstractController
{
25 protected $translator;
27 public function __construct(ContainerInterface
$container, TranslatorInterface
$translator, RouterInterface
$router) {
29 $this->config
= $container->getParameter($this->getAlias());
32 $this->translator
= $translator;
35 //XXX: we don't use this as it would be too slow, maybe ???
36 #$action = str_replace(self::getAlias().'_', '', $container->get('request_stack')->getCurrentRequest()->get('_route'));
38 //Inject every requested route in view and mail context
39 foreach($this->config
as $tag => $current) {
40 //Look for entry with route subkey
41 if (!empty($current['route'])) {
42 //Generate url for both view and mail
43 foreach(['view', 'mail'] as $view) {
44 //Check that context key is usable
45 if (isset($current[$view]['context']) && is_array($current[$view]['context'])) {
46 //Process every routes
47 foreach($current['route'] as $route => $key) {
48 //Skip recover_mail route as it requires some parameters
49 if ($route == 'recover_mail') {
52 //Check that key is empty
53 if (!isset($current[$view]['context'][$key])) {
55 $this->config
[$tag][$view]['context'][$key] = $router->generate(
56 $this->config
['route'][$route]['name'],
57 $this->config
['route'][$route]['context'],
58 //Generate absolute url for mails
59 $view=='mail'?UrlGeneratorInterface
::ABSOLUTE_URL
:UrlGeneratorInterface
::ABSOLUTE_PATH
69 public function login(Request
$request, AuthenticationUtils
$authenticationUtils) {
70 //Create the LoginType form and give the proper parameters
71 $form = $this->createForm($this->config
['login']['view']['form'], null, [
72 //Set action to login route name and context
73 'action' => $this->generateUrl($this->config
['route']['login']['name'], $this->config
['route']['login']['context']),
77 //Get the login error if there is one
78 if ($error = $authenticationUtils->getLastAuthenticationError()) {
79 //Get translated error
80 $error = $this->translator
->trans($error->getMessageKey());
82 //Add error message to mail field
83 $form->get('mail')->addError(new FormError($error));
86 //Last username entered by the user
87 if ($lastUsername = $authenticationUtils->getLastUsername()) {
88 $form->get('mail')->setData($lastUsername);
94 $this->config
['login']['view']['name'],
96 ['form' => $form->createView(), 'error' => $error]+
$this->config
['login']['view']['context']
100 public function recover(Request
$request, Slugger
$slugger, MailerInterface
$mailer) {
101 //Create the RecoverType form and give the proper parameters
102 $form = $this->createForm($this->config
['recover']['view']['form'], null, array(
103 //Set action to recover route name and context
104 'action' => $this->generateUrl($this->config
['route']['recover']['name'], $this->config
['route']['recover']['context']),
108 if ($request->isMethod('POST')) {
109 //Refill the fields in case the form is not valid.
110 $form->handleRequest($request);
112 if ($form->isValid()) {
114 $doctrine = $this->getDoctrine();
117 $data = $form->getData();
120 if ($user = $doctrine->getRepository($this->config
['class']['user'])->findOneByMail($data['mail'])) {
122 $mail =& $this->config
['recover']['mail'];
124 //Generate each route route
125 foreach($this->config
['recover']['route'] as $route => $tag) {
126 //Only process defined routes
127 if (empty($mail['context'][$tag]) && !empty($this->config
['route'][$route])) {
128 //Process for recover mail url
129 if ($route == 'recover_mail') {
130 //Prepend recover context with tag
131 $this->config
['route'][$route]['context'] = [
132 'recipient' => $slugger->short($user->getMail()),
133 'hash' => $slugger->hash($user->getPassword())
134 ]+
$this->config
['route'][$route]['context'];
136 //Set the url in context
137 $mail['context'][$tag] = $this->get('router')->generate(
138 $this->config
['route'][$route]['name'],
139 $this->config
['route'][$route]['context'],
140 UrlGeneratorInterface
::ABSOLUTE_URL
147 $mail['context']['recipient_mail'] = $data['mail'];
150 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
152 //Init subject context
153 $subjectContext = [];
155 //Process each context pair
156 foreach($mail['context']+
$this->config
['recover']['view']['context'] as $k => $v) {
157 //Reinsert each context pair with the key surrounded by %
158 $subjectContext['%'.$k.'%'] = $v;
162 $mail['subject'] = ucfirst($this->translator
->trans($mail['subject'], $subjectContext));
165 $message = (new TemplatedEmail())
167 ->from(new NamedAddress($this->config
['contact']['mail'], $this->config
['contact']['name']))
169 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
170 ->to(new NamedAddress($mail['context']['recipient_mail'], $mail['context']['recipient_name']))
172 ->subject($mail['subject'])
174 //Set path to twig templates
175 ->htmlTemplate($mail['html'])
176 ->textTemplate($mail['text'])
179 ->context(['subject' => $mail['subject']]+
$mail['context']+
$this->config
['recover']['view']['context']);
181 //Try sending message
182 //XXX: mail delivery may silently fail
185 $mailer->send($message);
187 //Redirect on the same route with sent=1 to cleanup form
188 #return $this->redirectToRoute('rapsys_user_register', array('sent' => 1));
189 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params'));
190 //Catch obvious transport exception
191 } catch(TransportExceptionInterface
$e) {
192 //Add error message mail unreachable
193 $form->get('mail')->addError(new FormError($this->translator
->trans('Account found but unable to contact: %mail%', array('%mail%' => $data['mail']))));
197 //Add error message to mail field
198 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to find account: %mail%', ['%mail%' => $data['mail']])));
204 return $this->render(
206 $this->config
['recover']['view']['name'],
208 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['recover']['view']['context']
212 public function recoverMail(Request
$request, UserPasswordEncoderInterface
$encoder, Slugger
$slugger, MailerInterface
$mailer, $recipient, $hash) {
213 //Create the RecoverType form and give the proper parameters
214 $form = $this->createForm($this->config
['recover_mail']['view']['form'], null, array(
215 //Set action to recover route name and context
216 'action' => $this->generateUrl($this->config
['route']['recover_mail']['name'], ['recipient' => $recipient, 'hash' => $hash]+
$this->config
['route']['recover_mail']['context']),
221 $doctrine = $this->getDoctrine();
227 if (($user = $doctrine->getRepository($this->config
['class']['user'])->findOneByMail($slugger->unshort($recipient))) && $hash == $slugger->hash($user->getPassword())) {
231 if ($request->isMethod('POST')) {
232 //Refill the fields in case the form is not valid.
233 $form->handleRequest($request);
235 if ($form->isValid()) {
237 $data = $form->getData();
239 //set encoded password
240 $encoded = $encoder->encodePassword($user, $data['password']);
243 $user->setPassword($encoded);
246 $manager = $doctrine->getManager();
249 $manager->persist($user);
255 $mail =& $this->config
['recover_mail']['mail'];
258 $hash = $slugger->hash($encoded);
260 //Generate each route route
261 foreach($this->config
['recover_mail']['route'] as $route => $tag) {
262 //Only process defined routes
263 if (empty($mail['context'][$tag]) && !empty($this->config
['route'][$route])) {
264 //Process for recover mail url
265 if ($route == 'recover_mail') {
266 //Prepend recover context with tag
267 $this->config
['route'][$route]['context'] = [
268 'recipient' => $recipient,
270 ]+
$this->config
['route'][$route]['context'];
272 //Set the url in context
273 $mail['context'][$tag] = $this->get('router')->generate(
274 $this->config
['route'][$route]['name'],
275 $this->config
['route'][$route]['context'],
276 UrlGeneratorInterface
::ABSOLUTE_URL
282 $mail['context']['recipient_mail'] = $user->getMail();
285 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
287 //Init subject context
288 $subjectContext = [];
290 //Process each context pair
291 foreach($mail['context']+
$this->config
['recover_mail']['view']['context'] as $k => $v) {
292 //Reinsert each context pair with the key surrounded by %
293 $subjectContext['%'.$k.'%'] = $v;
297 $mail['subject'] = ucfirst($this->translator
->trans($mail['subject'], $subjectContext));
300 $message = (new TemplatedEmail())
302 ->from(new NamedAddress($this->config
['contact']['mail'], $this->config
['contact']['name']))
304 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
305 ->to(new NamedAddress($mail['context']['recipient_mail'], $mail['context']['recipient_name']))
307 ->subject($mail['subject'])
309 //Set path to twig templates
310 ->htmlTemplate($mail['html'])
311 ->textTemplate($mail['text'])
314 ->context(['subject' => $mail['subject']]+
$mail['context']+
$this->config
['recover_mail']['view']['context']);
316 //Try sending message
317 //XXX: mail delivery may silently fail
320 $mailer->send($message);
322 //Redirect on the same route with sent=1 to cleanup form
323 return $this->redirectToRoute($request->get('_route'), ['recipient' => $recipient, 'hash' => $hash, 'sent' => 1]+
$request->get('_route_params'));
324 //Catch obvious transport exception
325 } catch(TransportExceptionInterface
$e) {
326 //Add error message mail unreachable
327 $form->get('mail')->addError(new FormError($this->translator
->trans('Account password updated but unable to contact: %mail%', array('%mail%' => $mail['context']['recipient_mail']))));
333 //Add error message to mail field
334 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to find account: %mail%', ['%mail%' => $slugger->unshort($recipient)])));
338 return $this->render(
340 $this->config
['recover_mail']['view']['name'],
342 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0), 'notfound' => $notfound]+
$this->config
['recover_mail']['view']['context']
346 public function register(Request
$request, UserPasswordEncoderInterface
$encoder, MailerInterface
$mailer) {
347 //Create the RegisterType form and give the proper parameters
348 $form = $this->createForm($this->config
['register']['view']['form'], null, array(
349 'class_title' => $this->config
['class']['title'],
350 //Set action to register route name and context
351 'action' => $this->generateUrl($this->config
['route']['register']['name'], $this->config
['route']['register']['context']),
355 if ($request->isMethod('POST')) {
356 //Refill the fields in case the form is not valid.
357 $form->handleRequest($request);
359 if ($form->isValid()) {
361 $data = $form->getData();
364 $mail =& $this->config
['register']['mail'];
366 //Generate each route route
367 foreach($this->config
['register']['route'] as $route => $tag) {
368 if (empty($mail['context'][$tag]) && !empty($this->config
['route'][$route])) {
369 $mail['context'][$tag] = $this->get('router')->generate(
370 $this->config
['route'][$route]['name'],
371 $this->config
['route'][$route]['context'],
372 UrlGeneratorInterface
::ABSOLUTE_URL
378 $mail['context']['recipient_mail'] = $data['mail'];
381 $mail['context']['recipient_name'] = trim($data['forename'].' '.$data['surname'].($data['pseudonym']?' ('.$data['pseudonym'].')':''));
383 //Init subject context
384 $subjectContext = [];
386 //Process each context pair
387 foreach($mail['context']+
$this->config
['register']['view']['context'] as $k => $v) {
388 //Reinsert each context pair with the key surrounded by %
389 $subjectContext['%'.$k.'%'] = $v;
393 $mail['subject'] = ucfirst($this->translator
->trans($mail['subject'], $subjectContext));
396 $message = (new TemplatedEmail())
398 ->from(new NamedAddress($this->config
['contact']['mail'], $this->config
['contact']['name']))
400 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
401 ->to(new NamedAddress($mail['context']['recipient_mail'], $mail['context']['recipient_name']))
403 ->subject($mail['subject'])
405 //Set path to twig templates
406 ->htmlTemplate($mail['html'])
407 ->textTemplate($mail['text'])
410 ->context(['subject' => $mail['subject']]+
$mail['context']+
$this->config
['register']['view']['context']);
413 $doctrine = $this->getDoctrine();
416 $manager = $doctrine->getManager();
419 $reflection = new \
ReflectionClass($this->config
['class']['user']);
422 $user = $reflection->newInstance();
424 $user->setMail($data['mail']);
425 $user->setPseudonym($data['pseudonym']);
426 $user->setForename($data['forename']);
427 $user->setSurname($data['surname']);
428 $user->setPhone($data['phone']);
429 $user->setPassword($encoder->encodePassword($user, $data['password']));
430 $user->setActive(true);
431 $user->setTitle($data['title']);
433 //XXX: For now there is no point in setting a role at subscription
434 //TODO: see if we can't modify group constructor to set role directly from args
435 //XXX: see vendor/symfony/symfony/src/Symfony/Component/Security/Core/Role/Role.php
436 #$user->addGroup($doctrine->getRepository($this->config['class']['group'])->findOneByRole('ROLE_USER'));
438 $user->setCreated(new \
DateTime('now'));
439 $user->setUpdated(new \
DateTime('now'));
442 $manager->persist($user);
444 //Try saving in database
449 //Try sending message
450 //XXX: mail delivery may silently fail
453 $mailer->send($message);
455 //Redirect on the same route with sent=1 to cleanup form
456 #return $this->redirectToRoute('rapsys_user_register', array('sent' => 1));
457 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params'));
458 //Catch obvious transport exception
459 } catch(TransportExceptionInterface
$e) {
460 //Add error message mail unreachable
461 $form->get('mail')->addError(new FormError($this->translator
->trans('Account created but unable to contact: %mail%', array('%mail%' => $data['mail']))));
463 //Catch double subscription
464 } catch (\Doctrine\DBAL\Exception\UniqueConstraintViolationException
$e) {
465 //Add error message mail already exists
466 $form->get('mail')->addError(new FormError($this->translator
->trans('Account already exists: %mail%', ['%mail%' => $data['mail']])));
472 return $this->render(
474 $this->config
['register']['view']['name'],
476 ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->config
['register']['view']['context']
483 public function getAlias() {
484 return 'rapsys_user';