Vérifier profil utilisateur complet - SimplonReunion/developpeur-web GitHub Wiki
Pour l'activité partage, vous avez, pour certains, eu besoins de vérifier si un utilisateur (particulier ou association) avait rempli complètement son profil avant de pouvoir utiliser l'application.
Pour faire ça, nous pouvons mettre en place un système qui se base sur les événements symfony. En effet, durant le processus de traitement d'une requête, symfony, déclenche des événements à différentes étapes. Par exemple, un événement est déclenché lorsque l'application reçoit une requête ou un autre avant que symfony appelle le bon contrôleur...
Pour faire ce que nous voulons, nous allons "écouter" l'événement kernel.controller
. Cet événement est appelé juste avant que le controller qui a été déterminé par la requête soit appelé.
Tout d'abord il faut créer le listener (écouteur) ce sera l'objet qui va écouter l'événement et qui sera appelé quand kernel.controller
sera déclenché.
//src/UserBundle/Listener/UserRegisterListener.php
namespace UserBundle\Listener;
use FOS\UserBundle\FOSUserEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
* Listener responsible to change the redirection at the end of the password resetting
*/
class UserRegisterListener implements EventSubscriberInterface
{
private $router;
private $authenticatedUser = null;
public function __construct(UrlGeneratorInterface $router, TokenStorageInterface $securityTokenStorage)
{
$this->router = $router;
if ($securityTokenStorage->getToken()) {
$this->authenticatedUser = $securityTokenStorage->getToken()->getUser();
}
}
/**
* {@inheritDoc}
*/
public static function getSubscribedEvents()
{
//enregistre l'événement à écouter et la méthode à appeler quand l'événement se produit
return array(
KernelEvents::CONTROLLER => 'checkUserProfileComplet',
);
}
/**
* Vérifie si le profil utilisateur est complet
*
* @param FilterControllerEvent $event
*/
public function checkUserProfileComplet(FilterControllerEvent $event)
{
}
}
Le point important ici est le tableau retourné par la méthode getSubscribedEvents
. C'est en se basant sur le tableau que symfony saura quel événement est écouté et quelle méthode sera appelée.
Mais pour que symfony connaisse vraiment que cette classe est un listener, il faut la définir en tant que service et le "tagguer" en tant que subscriber (souscripteur) :
# src/UserBundle/Resources/config/services.yml
services:
don.user_register_listener:
class: UserBundle\Listener\UserRegisterListener
arguments: ["@router","@security.token_storage"]
tags:
- { name: kernel.event_subscriber}
Nous passons 2 services à notre listener : router et security.token_storage. Le premier nous aidera à rediriger la requête vers l'url de complétion de profil et le deuxième permettra la récupération de l'utilisateur connecté afin de vérifier si le profil est complet.
Nous allons maintenant écrire la méthode qui va faire le travail :
/**
* Vérifie si le profil de l'utilisateur est complet
*
* @param FilterControllerEvent $event
* @return type
*/
public function checkUserProfileComplet(FilterControllerEvent $event)
{
//Fait la vérification que pour les requêtes principales, pas pour les requêtes secondaires.
if (!$event->isMasterRequest()) {
return;
}
//vérifie si la route est exempte de vérification
if (!$this->authorizeRoute($event->getRequest())) {
//On vérifie si l'utilisateur existe
if ($this->authenticatedUser !== null && is_object($this->authenticatedUser)) {
//On vérifie si l'utilisateur connecté en tant que Particulier a un profil incomplet
if (in_array('ROLE_PARTICULIER', $this->authenticatedUser->getRoles()) && $this->authenticatedUser->getParticulier() === null) {
//on redirige l'utilisateur vers la page où il va compléter son profil
$redirectUrl = $this->router->generate('particulier_register');
$event->setController(function() use ($redirectUrl) {
return new RedirectResponse($redirectUrl);
});
}
}
}
}
/**
* On vérifie si la route appelée est exempte de vérification
*
* @param Request $request
* @return boolean true si la route est autorisée false dans le cas contraire
*/
private function authorizeRoute(Request $request)
{
$path = $request->getPathInfo();
$routeName = $request->get('_route');
//On exempte de la vérification les routes: profiler, particulier_register, logout
if (preg_match("/^\/_profiler/", $path) ||
preg_match("/^\/_wdt/", $path) ||
$routeName == "particulier_register" ||
$routeName == "fos_user_security_logout"
) {
return true;
}
return false;
}
Bien que tout soit dit dans les commentaires plus haut, Nous allons revenir sur quelques points.
Nous remarquons checkUserProfileComplet
reçoit un objet $event
en paramètre. En effet, après que Symfony ait déterminé la méthode a appelé, il va lui passer un objet (de type FilterControllerEvent
) qui contient des informations qui nous sont utiles. Cet objet nous permettra de récupérer la requête, vérifier si la requête est une requête principale et rediriger vers l'URL qui permet de compléter le profil.
Nous n'allons pas rediriger toutes les requêtes. En effet, nous éviterons de rediriger le lien de déconnexion, celui qui permet de modifier son profil la méthode ou le profiler, par exemple.
Pour faire cette vérification, nous appellerons la méthode authorizeRoute
. Cette dernière a été écrite afin de tester l'URL ou la route pour vérifier si on doit faire la vérification de l'utilisateur ou pas.
Pour finir, dans l'activité l'utilisateur, celui-ci peut avoir comme rôle soit ROLE_PARTICULIER ou soit ROLE_ASSOCIATION. Ce que nous avons fait ici, ce n'est que pour la partie Particulier. Je vous laisse faire la partie Association.