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/DependencyInjection/SecurityExtension.php +445
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],