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 
{ 
  40          * @xxx Second argument will be replaced by security.firewalls.main.logout.target 
  41          * @see vendor/symfony/security-bundle/Resources/config/security_listeners.php +79 
  43         public function __construct(protected ContainerInterface 
$container, protected string $targetUrl, protected RouterInterface 
$router) { 
  45                 $this->config 
= $container->getParameter(RapsysUserBundle
::getAlias()); 
  51         public function onLogout(LogoutEvent 
$event): void { 
  53                 $request = $event->getRequest(); 
  55                 //Retrieve logout route 
  56                 $logout = $request->attributes
->get('_route'); 
  58                 //Extract and process referer 
  59                 if (($referer = $request->headers
->get('referer'))) { 
  60                         //Create referer request instance 
  61                         $req = Request
::create($referer); 
  64                         $path = $req->getPathInfo(); 
  66                         //Get referer query string 
  67                         $query = $req->getQueryString(); 
  70                         $path = str_replace($request->getScriptName(), '', $path); 
  72                         //Try with referer path 
  75                                 $oldContext = $this->router
->getContext(); 
  78                                 //XXX: prevent MethodNotAllowedException on GET only routes because our context method is POST 
  79                                 //XXX: see vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +42 
  80                                 $this->router
->setContext(new RequestContext()); 
  82                                 //Retrieve route matching path 
  83                                 $route = $this->router
->match($path); 
  86                                 $this->router
->setContext($oldContext); 
  91                                 //Without logout route name 
  92                                 if (($name = $route['_route']) != $logout) { 
  93                                         //Remove route and controller from route defaults 
  94                                         unset($route['_route'], $route['_controller'], $route['_canonical_route']); 
  97                                         $url = $this->router
->generate($name, $route); 
 100                                         $event->setResponse(new RedirectResponse($url, 302)); 
 104                                 //With logout route name 
 106                                         //Unset referer and route 
 107                                         unset($referer, $route); 
 110                         } catch (ResourceNotFoundException 
$e) { 
 111                                 //Unset referer and route 
 112                                 unset($referer, $route); 
 116                 //With index route from config 
 117                 if (!empty($name = $this->config
['route']['index']['name']) && is_array($context = $this->config
['route']['index']['context'])) { 
 118                         //Without logout route name 
 119                         if ($name != $logout) { 
 123                                         $url = $this->router
->generate($name, $context); 
 126                                         $event->setResponse(new RedirectResponse($url, 302)); 
 131                                 } catch (ResourceNotFoundException 
$e) { 
 132                                         //Unset name and context 
 133                                         unset($name, $context); 
 135                         //With logout route name 
 137                                 //Unset name and context 
 138                                 unset($name, $context); 
 145                         $oldContext = $this->router
->getContext(); 
 147                         //Force clean context 
 148                         //XXX: prevent MethodNotAllowedException on GET only routes because our context method is POST 
 149                         //XXX: see vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +42 
 150                         $this->router
->setContext(new RequestContext()); 
 152                         //With logout target path 
 153                         if ($this->targetUrl
[0] == '/') { 
 154                                 //Retrieve route matching target url 
 155                                 $route = $this->router
->match($this->targetUrl
); 
 158                                 $this->router
->setContext($oldContext); 
 163                                 //Without logout route name 
 164                                 if (($name = $route['_route']) != $logout) { 
 165                                         //Remove route and controller from route defaults 
 166                                         unset($route['_route'], $route['_controller'], $route['_canonical_route']); 
 169                                         $url = $this->router
->generate($name, $route); 
 172                                         $event->setResponse(new RedirectResponse($url, 302)); 
 176                                 //With logout route name 
 178                                         //Unset name and route 
 179                                         unset($name, $route); 
 183                                 //Retrieve route matching path 
 184                                 $url = $this->router
->generate($this->targetUrl
); 
 187                                 $event->setResponse(new RedirectResponse($url, 302)); 
 192                 //Get first route from route collection if / path was not matched 
 193                 } catch (ResourceNotFoundException
|RouteNotFoundException
|MissingMandatoryParametersException
|InvalidParameterException 
$e) { 
 194                         //Unset name and route 
 195                         unset($name, $route); 
 199                 $event->setResponse(new RedirectResponse('/', 302)); 
 205         public static function getSubscribedEvents(): array { 
 207                         LogoutEvent
::class => ['onLogout', 64],