]> Raphaël G. Git Repositories - userbundle/blob - Handler/LogoutSuccessHandler.php
825cd5b69bd5a7f973a0ad9b78185b5fca4ede3e
[userbundle] / Handler / LogoutSuccessHandler.php
1 <?php declare(strict_types=1);
2
3 /*
4 * This file is part of the Rapsys UserBundle package.
5 *
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Rapsys\UserBundle\Handler;
13
14 use Symfony\Component\DependencyInjection\ContainerInterface;
15 use Symfony\Component\HttpFoundation\RedirectResponse;
16 use Symfony\Component\HttpFoundation\Request;
17 use Symfony\Component\HttpFoundation\Response;
18 use Symfony\Component\Routing\Exception\ResourceNotFoundException;
19 use Symfony\Component\Routing\RequestContext;
20 use Symfony\Component\Routing\RouterInterface;
21 use Symfony\Component\Security\Http\Logout\DefaultLogoutSuccessHandler;
22
23 use Rapsys\UserBundle\RapsysUserBundle;
24
25 /**
26 * {@inheritdoc}
27 */
28 class LogoutSuccessHandler extends DefaultLogoutSuccessHandler {
29 /**
30 * Config array
31 */
32 protected $config;
33
34 /**
35 * {@inheritdoc}
36 */
37 protected $router;
38
39 /**
40 * {@inheritdoc}
41 */
42 protected $targetUrl;
43
44 /**
45 * @xxx Second argument will be replaced by security.firewalls.main.logout.target
46 * @see vendor/symfony/security-bundle/DependencyInjection/SecurityExtension.php +360
47 *
48 * {@inheritdoc}
49 */
50 public function __construct(ContainerInterface $container, string $targetUrl = '/', RouterInterface $router) {
51 //Set config
52 $this->config = $container->getParameter(self::getAlias());
53
54 //Set target url
55 $this->targetUrl = $targetUrl;
56
57 //Set router
58 $this->router = $router;
59 }
60
61 /**
62 * {@inheritdoc}
63 */
64 public function onLogoutSuccess(Request $request): Response {
65 //Retrieve logout route
66 $logout = $request->get('_route');
67
68 //Extract and process referer
69 if (($referer = $request->headers->get('referer'))) {
70 //Create referer request instance
71 $req = Request::create($referer);
72
73 //Get referer path
74 $path = $req->getPathInfo();
75
76 //Get referer query string
77 $query = $req->getQueryString();
78
79 //Remove script name
80 $path = str_replace($request->getScriptName(), '', $path);
81
82 //Try with referer path
83 try {
84 //Save old context
85 $oldContext = $this->router->getContext();
86
87 //Force clean context
88 //XXX: prevent MethodNotAllowedException on GET only routes because our context method is POST
89 //XXX: see vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +42
90 $this->router->setContext(new RequestContext());
91
92 //Retrieve route matching path
93 $route = $this->router->match($path);
94
95 //Reset context
96 $this->router->setContext($oldContext);
97
98 //Clear old context
99 unset($oldContext);
100
101 //Without logout route name
102 if (($name = $route['_route']) != $logout) {
103 //Remove route and controller from route defaults
104 unset($route['_route'], $route['_controller'], $route['_canonical_route']);
105
106 //Generate url
107 $url = $this->router->generate($name, $route);
108
109 //Return generated route
110 return new RedirectResponse($url, 302);
111 //With logout route name
112 } else {
113 //Unset referer and route
114 unset($referer, $route);
115 }
116 //No route matched
117 } catch (ResourceNotFoundException $e) {
118 //Unset referer and route
119 unset($referer, $route);
120 }
121 }
122
123 //With index route from config
124 if (!empty($name = $this->config['route']['index']['name']) && is_array($context = $this->config['route']['index']['context'])) {
125 //Without logout route name
126 if (($name = $route['_route']) != $logout) {
127 //Try index route
128 try {
129 //Generate url
130 $url = $this->router->generate($name, $context);
131
132 //Return generated route
133 return new RedirectResponse($url, 302);
134 //No route matched
135 } catch (ResourceNotFoundException $e) {
136 //Unset name and context
137 unset($name, $context);
138 }
139 //With logout route name
140 } else {
141 //Unset name and context
142 unset($name, $context);
143 }
144 }
145
146 //Try target url
147 try {
148 //Save old context
149 $oldContext = $this->router->getContext();
150
151 //Force clean context
152 //XXX: prevent MethodNotAllowedException on GET only routes because our context method is POST
153 //XXX: see vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php +42
154 $this->router->setContext(new RequestContext());
155
156 //Retrieve route matching target url
157 $route = $this->router->match($this->targetUrl);
158
159 //Reset context
160 $this->router->setContext($oldContext);
161
162 //Clear old context
163 unset($oldContext);
164
165 //Without logout route name
166 if (($name = $route['_route']) != $logout) {
167 //Remove route and controller from route defaults
168 unset($route['_route'], $route['_controller'], $route['_canonical_route']);
169
170 //Generate url
171 $url = $this->router->generate($name, $route);
172
173 //Return generated route
174 return new RedirectResponse($url, 302);
175 //With logout route name
176 } else {
177 //Unset name and route
178 unset($name, $route);
179 }
180 //Get first route from route collection if / path was not matched
181 } catch (ResourceNotFoundException $e) {
182 //Unset name and route
183 unset($name, $route);
184 }
185
186 //Throw exception
187 throw new \RuntimeException('You must provide a valid logout target url or route name');
188 }
189
190 /**
191 * {@inheritdoc}
192 */
193 public function getAlias(): string {
194 return RapsysUserBundle::getAlias();
195 }
196 }