]> Raphaƫl G. Git Repositories - userbundle/blob - Controller/DefaultController.php
9f2e2b5700765236c555dd4a6e6fe5bd02286d06
[userbundle] / Controller / DefaultController.php
1 <?php
2
3 namespace Rapsys\UserBundle\Controller;
4
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;
19
20 class DefaultController extends AbstractController {
21 //Config array
22 protected $config;
23
24 //Translator instance
25 protected $translator;
26
27 public function __construct(ContainerInterface $container, TranslatorInterface $translator, RouterInterface $router) {
28 //Retrieve config
29 $this->config = $container->getParameter($this->getAlias());
30
31 //Set the translator
32 $this->translator = $translator;
33
34 //Get current action
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'));
37
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') {
50 continue;
51 }
52 //Check that key is empty
53 if (!isset($current[$view]['context'][$key])) {
54 //Generate the route
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
60 );
61 }
62 }
63 }
64 }
65 }
66 }
67 }
68
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']),
74 'method' => 'POST'
75 ]);
76
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());
81
82 //Add error message to mail field
83 $form->get('mail')->addError(new FormError($error));
84 }
85
86 //Last username entered by the user
87 if ($lastUsername = $authenticationUtils->getLastUsername()) {
88 $form->get('mail')->setData($lastUsername);
89 }
90
91 //Render view
92 return $this->render(
93 //Template
94 $this->config['login']['view']['name'],
95 //Context
96 ['form' => $form->createView(), 'error' => $error]+$this->config['login']['view']['context']
97 );
98 }
99
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']),
105 'method' => 'POST'
106 ));
107
108 if ($request->isMethod('POST')) {
109 //Refill the fields in case the form is not valid.
110 $form->handleRequest($request);
111
112 if ($form->isValid()) {
113 //Get doctrine
114 $doctrine = $this->getDoctrine();
115
116 //Set data
117 $data = $form->getData();
118
119 //Try to find user
120 if ($user = $doctrine->getRepository($this->config['class']['user'])->findOneByMail($data['mail'])) {
121 //Set mail shortcut
122 $mail =& $this->config['recover']['mail'];
123
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'];
135 }
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
141 );
142
143 }
144 }
145
146 //Set recipient_name
147 $mail['context']['recipient_mail'] = $data['mail'];
148
149 //Set recipient_name
150 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
151
152 //Init subject context
153 $subjectContext = [];
154
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;
159 }
160
161 //Translate subject
162 $mail['subject'] = ucfirst($this->translator->trans($mail['subject'], $subjectContext));
163
164 //Create message
165 $message = (new TemplatedEmail())
166 //Set sender
167 ->from(new NamedAddress($this->config['contact']['mail'], $this->config['contact']['name']))
168 //Set recipient
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']))
171 //Set subject
172 ->subject($mail['subject'])
173
174 //Set path to twig templates
175 ->htmlTemplate($mail['html'])
176 ->textTemplate($mail['text'])
177
178 //Set context
179 ->context(['subject' => $mail['subject']]+$mail['context']+$this->config['recover']['view']['context']);
180
181 //Try sending message
182 //XXX: mail delivery may silently fail
183 try {
184 //Send message
185 $mailer->send($message);
186
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']))));
194 }
195 //Accout not found
196 } else {
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']])));
199 }
200 }
201 }
202
203 //Render view
204 return $this->render(
205 //Template
206 $this->config['recover']['view']['name'],
207 //Context
208 ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['recover']['view']['context']
209 );
210 }
211
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']),
217 'method' => 'POST'
218 ));
219
220 //Get doctrine
221 $doctrine = $this->getDoctrine();
222
223 //Init not found
224 $notfound = 1;
225
226 //Retrieve user
227 if (($user = $doctrine->getRepository($this->config['class']['user'])->findOneByMail($slugger->unshort($recipient))) && $hash == $slugger->hash($user->getPassword())) {
228 //User was found
229 $notfound = 0;
230
231 if ($request->isMethod('POST')) {
232 //Refill the fields in case the form is not valid.
233 $form->handleRequest($request);
234
235 if ($form->isValid()) {
236 //Set data
237 $data = $form->getData();
238
239 //set encoded password
240 $encoded = $encoder->encodePassword($user, $data['password']);
241
242 //Set user password
243 $user->setPassword($encoded);
244
245 //Get manager
246 $manager = $doctrine->getManager();
247
248 //Persist user
249 $manager->persist($user);
250
251 //Send to database
252 $manager->flush();
253
254 //Set mail shortcut
255 $mail =& $this->config['recover_mail']['mail'];
256
257 //Regen hash
258 $hash = $slugger->hash($encoded);
259
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,
269 'hash' => $hash
270 ]+$this->config['route'][$route]['context'];
271 }
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
277 );
278 }
279 }
280
281 //Set recipient_name
282 $mail['context']['recipient_mail'] = $user->getMail();
283
284 //Set recipient_name
285 $mail['context']['recipient_name'] = trim($user->getForename().' '.$user->getSurname().($user->getPseudonym()?' ('.$user->getPseudonym().')':''));
286
287 //Init subject context
288 $subjectContext = [];
289
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;
294 }
295
296 //Translate subject
297 $mail['subject'] = ucfirst($this->translator->trans($mail['subject'], $subjectContext));
298
299 //Create message
300 $message = (new TemplatedEmail())
301 //Set sender
302 ->from(new NamedAddress($this->config['contact']['mail'], $this->config['contact']['name']))
303 //Set recipient
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']))
306 //Set subject
307 ->subject($mail['subject'])
308
309 //Set path to twig templates
310 ->htmlTemplate($mail['html'])
311 ->textTemplate($mail['text'])
312
313 //Set context
314 ->context(['subject' => $mail['subject']]+$mail['context']+$this->config['recover_mail']['view']['context']);
315
316 //Try sending message
317 //XXX: mail delivery may silently fail
318 try {
319 //Send message
320 $mailer->send($message);
321
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']))));
328 }
329 }
330 }
331 //Accout not found
332 } else {
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)])));
335 }
336
337 //Render view
338 return $this->render(
339 //Template
340 $this->config['recover_mail']['view']['name'],
341 //Context
342 ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0), 'notfound' => $notfound]+$this->config['recover_mail']['view']['context']
343 );
344 }
345
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']),
352 'method' => 'POST'
353 ));
354
355 if ($request->isMethod('POST')) {
356 //Refill the fields in case the form is not valid.
357 $form->handleRequest($request);
358
359 if ($form->isValid()) {
360 //Set data
361 $data = $form->getData();
362
363 //Set mail shortcut
364 $mail =& $this->config['register']['mail'];
365
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
373 );
374 }
375 }
376
377 //Set recipient_name
378 $mail['context']['recipient_mail'] = $data['mail'];
379
380 //Set recipient_name
381 $mail['context']['recipient_name'] = trim($data['forename'].' '.$data['surname'].($data['pseudonym']?' ('.$data['pseudonym'].')':''));
382
383 //Init subject context
384 $subjectContext = [];
385
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;
390 }
391
392 //Translate subject
393 $mail['subject'] = ucfirst($this->translator->trans($mail['subject'], $subjectContext));
394
395 //Create message
396 $message = (new TemplatedEmail())
397 //Set sender
398 ->from(new NamedAddress($this->config['contact']['mail'], $this->config['contact']['name']))
399 //Set recipient
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']))
402 //Set subject
403 ->subject($mail['subject'])
404
405 //Set path to twig templates
406 ->htmlTemplate($mail['html'])
407 ->textTemplate($mail['text'])
408
409 //Set context
410 ->context(['subject' => $mail['subject']]+$mail['context']+$this->config['register']['view']['context']);
411
412 //Get doctrine
413 $doctrine = $this->getDoctrine();
414
415 //Get manager
416 $manager = $doctrine->getManager();
417
418 //Init reflection
419 $reflection = new \ReflectionClass($this->config['class']['user']);
420
421 //Create new user
422 $user = $reflection->newInstance();
423
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']);
432
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'));
437
438 $user->setCreated(new \DateTime('now'));
439 $user->setUpdated(new \DateTime('now'));
440
441 //Persist user
442 $manager->persist($user);
443
444 //Try saving in database
445 try {
446 //Send to database
447 $manager->flush();
448
449 //Try sending message
450 //XXX: mail delivery may silently fail
451 try {
452 //Send message
453 $mailer->send($message);
454
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']))));
462 }
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']])));
467 }
468 }
469 }
470
471 //Render view
472 return $this->render(
473 //Template
474 $this->config['register']['view']['name'],
475 //Context
476 ['form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->config['register']['view']['context']
477 );
478 }
479
480 /**
481 * {@inheritdoc}
482 */
483 public function getAlias() {
484 return 'rapsys_user';
485 }
486 }