13
13
14
14
use Symfony \Component \HttpFoundation \RequestStack ;
15
15
use Symfony \Component \Routing \Generator \UrlGeneratorInterface ;
16
+ use Symfony \Component \Security \Core \Authentication \Token \AnonymousToken ;
16
17
use Symfony \Component \Security \Core \Authentication \Token \Storage \TokenStorageInterface ;
17
18
use Symfony \Component \Security \Csrf \CsrfTokenManagerInterface ;
18
19
@@ -28,6 +29,7 @@ class LogoutUrlGenerator
28
29
private $ router ;
29
30
private $ tokenStorage ;
30
31
private $ listeners = array ();
32
+ private $ currentFirewall ;
31
33
32
34
public function __construct (RequestStack $ requestStack = null , UrlGeneratorInterface $ router = null , TokenStorageInterface $ tokenStorage = null )
33
35
{
@@ -39,15 +41,29 @@ public function __construct(RequestStack $requestStack = null, UrlGeneratorInter
39
41
/**
40
42
* Registers a firewall's LogoutListener, allowing its URL to be generated.
41
43
*
42
- * @param string $key The firewall key
43
- * @param string $logoutPath The path that starts the logout process
44
- * @param string $csrfTokenId The ID of the CSRF token
45
- * @param string $csrfParameter The CSRF token parameter name
46
- * @param CsrfTokenManagerInterface $csrfTokenManager A CsrfTokenManagerInterface instance
44
+ * @param string $key The firewall key
45
+ * @param string $logoutPath The path that starts the logout process
46
+ * @param string $csrfTokenId The ID of the CSRF token
47
+ * @param string $csrfParameter The CSRF token parameter name
48
+ * @param CsrfTokenManagerInterface|null $csrfTokenManager A CsrfTokenManagerInterface instance
49
+ * @param string|null $context The listener context
47
50
*/
48
- public function registerListener ($ key , $ logoutPath , $ csrfTokenId , $ csrfParameter , CsrfTokenManagerInterface $ csrfTokenManager = null )
51
+ public function registerListener ($ key , $ logoutPath , $ csrfTokenId , $ csrfParameter , CsrfTokenManagerInterface $ csrfTokenManager = null /*, $context = null*/ )
49
52
{
50
- $ this ->listeners [$ key ] = array ($ logoutPath , $ csrfTokenId , $ csrfParameter , $ csrfTokenManager );
53
+ if (func_num_args () >= 6 ) {
54
+ $ context = func_get_arg (5 );
55
+ } else {
56
+ if (__CLASS__ !== get_class ($ this )) {
57
+ $ r = new \ReflectionMethod ($ this , __FUNCTION__ );
58
+ if (__CLASS__ !== $ r ->getDeclaringClass ()->getName ()) {
59
+ @trigger_error (sprintf ('Method %s() will have a sixth `$context = null` argument in version 4.0. Not defining it is deprecated since 3.3. ' , get_class ($ this ), __FUNCTION__ ), E_USER_DEPRECATED );
60
+ }
61
+ }
62
+
63
+ $ context = null ;
64
+ }
65
+
66
+ $ this ->listeners [$ key ] = array ($ logoutPath , $ csrfTokenId , $ csrfParameter , $ csrfTokenManager , $ context );
51
67
}
52
68
53
69
/**
@@ -74,35 +90,26 @@ public function getLogoutUrl($key = null)
74
90
return $ this ->generateLogoutUrl ($ key , UrlGeneratorInterface::ABSOLUTE_URL );
75
91
}
76
92
93
+ /**
94
+ * @param string|null $key The current firewall key
95
+ * @param string|null $context The current firewall context
96
+ */
97
+ public function setCurrentFirewall ($ key , $ context = null )
98
+ {
99
+ $ this ->currentFirewall = array ($ key , $ context );
100
+ }
101
+
77
102
/**
78
103
* Generates the logout URL for the firewall.
79
104
*
80
105
* @param string|null $key The firewall key or null to use the current firewall key
81
106
* @param int $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
82
107
*
83
108
* @return string The logout URL
84
- *
85
- * @throws \InvalidArgumentException if no LogoutListener is registered for the key or the key could not be found automatically.
86
109
*/
87
110
private function generateLogoutUrl ($ key , $ referenceType )
88
111
{
89
- // Fetch the current provider key from token, if possible
90
- if (null === $ key && null !== $ this ->tokenStorage ) {
91
- $ token = $ this ->tokenStorage ->getToken ();
92
- if (null !== $ token && method_exists ($ token , 'getProviderKey ' )) {
93
- $ key = $ token ->getProviderKey ();
94
- }
95
- }
96
-
97
- if (null === $ key ) {
98
- throw new \InvalidArgumentException ('Unable to find the current firewall LogoutListener, please provide the provider key manually. ' );
99
- }
100
-
101
- if (!array_key_exists ($ key , $ this ->listeners )) {
102
- throw new \InvalidArgumentException (sprintf ('No LogoutListener found for firewall key "%s". ' , $ key ));
103
- }
104
-
105
- list ($ logoutPath , $ csrfTokenId , $ csrfParameter , $ csrfTokenManager ) = $ this ->listeners [$ key ];
112
+ list ($ logoutPath , $ csrfTokenId , $ csrfParameter , $ csrfTokenManager ) = $ this ->getListener ($ key );
106
113
107
114
$ parameters = null !== $ csrfTokenManager ? array ($ csrfParameter => (string ) $ csrfTokenManager ->getToken ($ csrfTokenId )) : array ();
108
115
@@ -128,4 +135,54 @@ private function generateLogoutUrl($key, $referenceType)
128
135
129
136
return $ url ;
130
137
}
138
+
139
+ /**
140
+ * @param string|null $key The firewall key or null use the current firewall key
141
+ *
142
+ * @return array The logout listener found
143
+ *
144
+ * @throws \InvalidArgumentException if no LogoutListener is registered for the key or could not be found automatically.
145
+ */
146
+ private function getListener ($ key )
147
+ {
148
+ if (null !== $ key ) {
149
+ if (isset ($ this ->listeners [$ key ])) {
150
+ return $ this ->listeners [$ key ];
151
+ }
152
+
153
+ throw new \InvalidArgumentException (sprintf ('No LogoutListener found for firewall key "%s". ' , $ key ));
154
+ }
155
+
156
+ // Fetch the current provider key from token, if possible
157
+ if (null !== $ this ->tokenStorage ) {
158
+ $ token = $ this ->tokenStorage ->getToken ();
159
+
160
+ if ($ token instanceof AnonymousToken) {
161
+ throw new \InvalidArgumentException ('Unable to generate a logout url for an anonymous token. ' );
162
+ }
163
+
164
+ if (null !== $ token && method_exists ($ token , 'getProviderKey ' )) {
165
+ $ key = $ token ->getProviderKey ();
166
+
167
+ if (isset ($ this ->listeners [$ key ])) {
168
+ return $ this ->listeners [$ key ];
169
+ }
170
+ }
171
+ }
172
+
173
+ // Fetch from injected current firewall information, if possible
174
+ list ($ key , $ context ) = $ this ->currentFirewall ;
175
+
176
+ if (isset ($ this ->listeners [$ key ])) {
177
+ return $ this ->listeners [$ key ];
178
+ }
179
+
180
+ foreach ($ this ->listeners as $ listener ) {
181
+ if (isset ($ listener [4 ]) && $ context === $ listener [4 ]) {
182
+ return $ listener ;
183
+ }
184
+ }
185
+
186
+ throw new \InvalidArgumentException ('Unable to find the current firewall LogoutListener, please provide the provider key manually. ' );
187
+ }
131
188
}
0 commit comments