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\Listener
; 
  14 use Symfony\Component\DependencyInjection\ContainerInterface
; 
  15 use Symfony\Component\EventDispatcher\EventSubscriberInterface
; 
  16 use Symfony\Component\HttpFoundation\RedirectResponse
; 
  17 use Symfony\Component\HttpFoundation\Request
; 
  18 use Symfony\Component\Routing\Exception\InvalidParameterException
; 
  19 use Symfony\Component\Routing\Exception\MissingMandatoryParametersException
; 
  20 use Symfony\Component\Routing\Exception\ResourceNotFoundException
; 
  21 use Symfony\Component\Routing\Exception\RouteNotFoundException
; 
  22 use Symfony\Component\Routing\RequestContext
; 
  23 use Symfony\Component\Routing\RouterInterface
; 
  24 use Symfony\Component\Security\Http\Event\LogoutEvent
; 
  26 use Rapsys\UserBundle\RapsysUserBundle
; 
  31 class LogoutListener 
implements EventSubscriberInterface 
{ 
  45          * @xxx Second argument will be replaced by security.firewalls.main.logout.target 
  46          * @see vendor/symfony/security-bundle/Resources/config/security_listeners.php +79 
  48         public function __construct(ContainerInterface 
$container, string $targetUrl, RouterInterface 
$router) { 
  50                 $this->config 
= $container->getParameter(RapsysUserBundle
::getAlias()); 
  53                 $this->targetUrl 
= $targetUrl; 
  56                 $this->router 
= $router; 
  62         public function onLogout(LogoutEvent 
$event): void { 
  64                 $request = $event->getRequest(); 
  66                 //Retrieve logout route 
  67                 $logout = $request->attributes
->get('_route'); 
  69                 //Extract and process referer 
  70                 if (($referer = $request->headers
->get('referer'))) { 
  71                         //Create referer request instance 
  72                         $req = Request
::create($referer); 
  75                         $path = $req->getPathInfo(); 
  77                         //Get referer query string 
  78                         $query = $req->getQueryString(); 
  81                         $path = str_replace($request->getScriptName(), '', $path); 
  83                         //Try with referer path 
  86                                 $oldContext = $this->router
->getContext(); 
  89                                 //XXX: prevent MethodNotAllowedException on GET only routes because our context method is POST 
  90                                 //XXX: see vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +42 
  91                                 $this->router
->setContext(new RequestContext()); 
  93                                 //Retrieve route matching path 
  94                                 $route = $this->router
->match($path); 
  97                                 $this->router
->setContext($oldContext); 
 102                                 //Without logout route name 
 103                                 if (($name = $route['_route']) != $logout) { 
 104                                         //Remove route and controller from route defaults 
 105                                         unset($route['_route'], $route['_controller'], $route['_canonical_route']); 
 108                                         $url = $this->router
->generate($name, $route); 
 111                                         $event->setResponse(new RedirectResponse($url, 302)); 
 115                                 //With logout route name 
 117                                         //Unset referer and route 
 118                                         unset($referer, $route); 
 121                         } catch (ResourceNotFoundException 
$e) { 
 122                                 //Unset referer and route 
 123                                 unset($referer, $route); 
 127                 //With index route from config 
 128                 if (!empty($name = $this->config
['route']['index']['name']) && is_array($context = $this->config
['route']['index']['context'])) { 
 129                         //Without logout route name 
 130                         if ($name != $logout) { 
 134                                         $url = $this->router
->generate($name, $context); 
 137                                         $event->setResponse(new RedirectResponse($url, 302)); 
 142                                 } catch (ResourceNotFoundException 
$e) { 
 143                                         //Unset name and context 
 144                                         unset($name, $context); 
 146                         //With logout route name 
 148                                 //Unset name and context 
 149                                 unset($name, $context); 
 156                         $oldContext = $this->router
->getContext(); 
 158                         //Force clean context 
 159                         //XXX: prevent MethodNotAllowedException on GET only routes because our context method is POST 
 160                         //XXX: see vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +42 
 161                         $this->router
->setContext(new RequestContext()); 
 163                         //With logout target path 
 164                         if ($this->targetUrl
[0] == '/') { 
 165                                 //Retrieve route matching target url 
 166                                 $route = $this->router
->match($this->targetUrl
); 
 169                                 $this->router
->setContext($oldContext); 
 174                                 //Without logout route name 
 175                                 if (($name = $route['_route']) != $logout) { 
 176                                         //Remove route and controller from route defaults 
 177                                         unset($route['_route'], $route['_controller'], $route['_canonical_route']); 
 180                                         $url = $this->router
->generate($name, $route); 
 183                                         $event->setResponse(new RedirectResponse($url, 302)); 
 187                                 //With logout route name 
 189                                         //Unset name and route 
 190                                         unset($name, $route); 
 194                                 //Retrieve route matching path 
 195                                 $url = $this->router
->generate($this->targetUrl
); 
 198                                 $event->setResponse(new RedirectResponse($url, 302)); 
 203                 //Get first route from route collection if / path was not matched 
 204                 } catch (ResourceNotFoundException
|RouteNotFoundException
|MissingMandatoryParametersException
|InvalidParameterException 
$e) { 
 205                         //Unset name and route 
 206                         unset($name, $route); 
 210                 $event->setResponse(new RedirectResponse('/', 302)); 
 216         public static function getSubscribedEvents(): array { 
 218                         LogoutEvent
::class => ['onLogout', 64],