12
12
namespace Symfony \Component \HttpKernel \Tests \Controller ;
13
13
14
14
use PHPUnit \Framework \TestCase ;
15
+ use Symfony \Component \DependencyInjection \ServiceLocator ;
15
16
use Symfony \Component \HttpFoundation \Request ;
16
17
use Symfony \Component \HttpFoundation \Session \Session ;
17
18
use Symfony \Component \HttpFoundation \Session \SessionInterface ;
18
19
use Symfony \Component \HttpFoundation \Session \Storage \MockArraySessionStorage ;
20
+ use Symfony \Component \HttpKernel \Attribute \ValueResolver ;
19
21
use Symfony \Component \HttpKernel \Controller \ArgumentResolver ;
22
+ use Symfony \Component \HttpKernel \Controller \ArgumentResolver \DefaultValueResolver ;
20
23
use Symfony \Component \HttpKernel \Controller \ArgumentResolver \RequestAttributeValueResolver ;
21
24
use Symfony \Component \HttpKernel \Controller \ArgumentValueResolverInterface ;
22
25
use Symfony \Component \HttpKernel \ControllerMetadata \ArgumentMetadataFactory ;
26
+ use Symfony \Component \HttpKernel \Exception \ResolverNotFoundException ;
23
27
use Symfony \Component \HttpKernel \Tests \Fixtures \Controller \ExtendingRequest ;
24
28
use Symfony \Component \HttpKernel \Tests \Fixtures \Controller \ExtendingSession ;
25
29
use Symfony \Component \HttpKernel \Tests \Fixtures \Controller \NullableController ;
26
30
use Symfony \Component \HttpKernel \Tests \Fixtures \Controller \VariadicController ;
27
31
28
32
class ArgumentResolverTest extends TestCase
29
33
{
30
- /** @var ArgumentResolver */
31
- private static $ resolver ;
32
-
33
- public static function setUpBeforeClass (): void
34
+ public static function getResolver (array $ chainableResolvers = [], array $ namedResolvers = null ): ArgumentResolver
34
35
{
35
- $ factory = new ArgumentMetadataFactory ();
36
+ if (null !== $ namedResolvers ) {
37
+ $ namedResolvers = new ServiceLocator (array_map (fn ($ resolver ) => fn () => $ resolver , $ namedResolvers ));
38
+ }
36
39
37
- self :: $ resolver = new ArgumentResolver ($ factory );
40
+ return new ArgumentResolver (new ArgumentMetadataFactory (), $ chainableResolvers , $ namedResolvers );
38
41
}
39
42
40
43
public function testDefaultState ()
41
44
{
42
- $ this ->assertEquals (self ::$ resolver , new ArgumentResolver ());
43
- $ this ->assertNotEquals (self ::$ resolver , new ArgumentResolver (null , [new RequestAttributeValueResolver ()]));
45
+ $ this ->assertEquals (self ::getResolver () , new ArgumentResolver ());
46
+ $ this ->assertNotEquals (self ::getResolver () , new ArgumentResolver (null , [new RequestAttributeValueResolver ()]));
44
47
}
45
48
46
49
public function testGetArguments ()
@@ -49,15 +52,15 @@ public function testGetArguments()
49
52
$ request ->attributes ->set ('foo ' , 'foo ' );
50
53
$ controller = [new self (), 'controllerWithFoo ' ];
51
54
52
- $ this ->assertEquals (['foo ' ], self ::$ resolver ->getArguments ($ request , $ controller ), '->getArguments() returns an array of arguments for the controller method ' );
55
+ $ this ->assertEquals (['foo ' ], self ::getResolver () ->getArguments ($ request , $ controller ), '->getArguments() returns an array of arguments for the controller method ' );
53
56
}
54
57
55
58
public function testGetArgumentsReturnsEmptyArrayWhenNoArguments ()
56
59
{
57
60
$ request = Request::create ('/ ' );
58
61
$ controller = [new self (), 'controllerWithoutArguments ' ];
59
62
60
- $ this ->assertEquals ([], self ::$ resolver ->getArguments ($ request , $ controller ), '->getArguments() returns an empty array if the method takes no arguments ' );
63
+ $ this ->assertEquals ([], self ::getResolver () ->getArguments ($ request , $ controller ), '->getArguments() returns an empty array if the method takes no arguments ' );
61
64
}
62
65
63
66
public function testGetArgumentsUsesDefaultValue ()
@@ -66,7 +69,7 @@ public function testGetArgumentsUsesDefaultValue()
66
69
$ request ->attributes ->set ('foo ' , 'foo ' );
67
70
$ controller = [new self (), 'controllerWithFooAndDefaultBar ' ];
68
71
69
- $ this ->assertEquals (['foo ' , null ], self ::$ resolver ->getArguments ($ request , $ controller ), '->getArguments() uses default values if present ' );
72
+ $ this ->assertEquals (['foo ' , null ], self ::getResolver () ->getArguments ($ request , $ controller ), '->getArguments() uses default values if present ' );
70
73
}
71
74
72
75
public function testGetArgumentsOverrideDefaultValueByRequestAttribute ()
@@ -76,7 +79,7 @@ public function testGetArgumentsOverrideDefaultValueByRequestAttribute()
76
79
$ request ->attributes ->set ('bar ' , 'bar ' );
77
80
$ controller = [new self (), 'controllerWithFooAndDefaultBar ' ];
78
81
79
- $ this ->assertEquals (['foo ' , 'bar ' ], self ::$ resolver ->getArguments ($ request , $ controller ), '->getArguments() overrides default values if provided in the request attributes ' );
82
+ $ this ->assertEquals (['foo ' , 'bar ' ], self ::getResolver () ->getArguments ($ request , $ controller ), '->getArguments() overrides default values if provided in the request attributes ' );
80
83
}
81
84
82
85
public function testGetArgumentsFromClosure ()
@@ -85,7 +88,7 @@ public function testGetArgumentsFromClosure()
85
88
$ request ->attributes ->set ('foo ' , 'foo ' );
86
89
$ controller = function ($ foo ) {};
87
90
88
- $ this ->assertEquals (['foo ' ], self ::$ resolver ->getArguments ($ request , $ controller ));
91
+ $ this ->assertEquals (['foo ' ], self ::getResolver () ->getArguments ($ request , $ controller ));
89
92
}
90
93
91
94
public function testGetArgumentsUsesDefaultValueFromClosure ()
@@ -94,7 +97,7 @@ public function testGetArgumentsUsesDefaultValueFromClosure()
94
97
$ request ->attributes ->set ('foo ' , 'foo ' );
95
98
$ controller = function ($ foo , $ bar = 'bar ' ) {};
96
99
97
- $ this ->assertEquals (['foo ' , 'bar ' ], self ::$ resolver ->getArguments ($ request , $ controller ));
100
+ $ this ->assertEquals (['foo ' , 'bar ' ], self ::getResolver () ->getArguments ($ request , $ controller ));
98
101
}
99
102
100
103
public function testGetArgumentsFromInvokableObject ()
@@ -103,12 +106,12 @@ public function testGetArgumentsFromInvokableObject()
103
106
$ request ->attributes ->set ('foo ' , 'foo ' );
104
107
$ controller = new self ();
105
108
106
- $ this ->assertEquals (['foo ' , null ], self ::$ resolver ->getArguments ($ request , $ controller ));
109
+ $ this ->assertEquals (['foo ' , null ], self ::getResolver () ->getArguments ($ request , $ controller ));
107
110
108
111
// Test default bar overridden by request attribute
109
112
$ request ->attributes ->set ('bar ' , 'bar ' );
110
113
111
- $ this ->assertEquals (['foo ' , 'bar ' ], self ::$ resolver ->getArguments ($ request , $ controller ));
114
+ $ this ->assertEquals (['foo ' , 'bar ' ], self ::getResolver () ->getArguments ($ request , $ controller ));
112
115
}
113
116
114
117
public function testGetArgumentsFromFunctionName ()
@@ -118,7 +121,7 @@ public function testGetArgumentsFromFunctionName()
118
121
$ request ->attributes ->set ('foobar ' , 'foobar ' );
119
122
$ controller = __NAMESPACE__ .'\controller_function ' ;
120
123
121
- $ this ->assertEquals (['foo ' , 'foobar ' ], self ::$ resolver ->getArguments ($ request , $ controller ));
124
+ $ this ->assertEquals (['foo ' , 'foobar ' ], self ::getResolver () ->getArguments ($ request , $ controller ));
122
125
}
123
126
124
127
public function testGetArgumentsFailsOnUnresolvedValue ()
@@ -129,7 +132,7 @@ public function testGetArgumentsFailsOnUnresolvedValue()
129
132
$ controller = [new self (), 'controllerWithFooBarFoobar ' ];
130
133
131
134
try {
132
- self ::$ resolver ->getArguments ($ request , $ controller );
135
+ self ::getResolver () ->getArguments ($ request , $ controller );
133
136
$ this ->fail ('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value ' );
134
137
} catch (\Exception $ e ) {
135
138
$ this ->assertInstanceOf (\RuntimeException::class, $ e , '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value ' );
@@ -141,15 +144,15 @@ public function testGetArgumentsInjectsRequest()
141
144
$ request = Request::create ('/ ' );
142
145
$ controller = [new self (), 'controllerWithRequest ' ];
143
146
144
- $ this ->assertEquals ([$ request ], self ::$ resolver ->getArguments ($ request , $ controller ), '->getArguments() injects the request ' );
147
+ $ this ->assertEquals ([$ request ], self ::getResolver () ->getArguments ($ request , $ controller ), '->getArguments() injects the request ' );
145
148
}
146
149
147
150
public function testGetArgumentsInjectsExtendingRequest ()
148
151
{
149
152
$ request = ExtendingRequest::create ('/ ' );
150
153
$ controller = [new self (), 'controllerWithExtendingRequest ' ];
151
154
152
- $ this ->assertEquals ([$ request ], self ::$ resolver ->getArguments ($ request , $ controller ), '->getArguments() injects the request when extended ' );
155
+ $ this ->assertEquals ([$ request ], self ::getResolver () ->getArguments ($ request , $ controller ), '->getArguments() injects the request when extended ' );
153
156
}
154
157
155
158
public function testGetVariadicArguments ()
@@ -159,7 +162,7 @@ public function testGetVariadicArguments()
159
162
$ request ->attributes ->set ('bar ' , ['foo ' , 'bar ' ]);
160
163
$ controller = [new VariadicController (), 'action ' ];
161
164
162
- $ this ->assertEquals (['foo ' , 'foo ' , 'bar ' ], self ::$ resolver ->getArguments ($ request , $ controller ));
165
+ $ this ->assertEquals (['foo ' , 'foo ' , 'bar ' ], self ::getResolver () ->getArguments ($ request , $ controller ));
163
166
}
164
167
165
168
public function testGetVariadicArgumentsWithoutArrayInRequest ()
@@ -170,7 +173,7 @@ public function testGetVariadicArgumentsWithoutArrayInRequest()
170
173
$ request ->attributes ->set ('bar ' , 'foo ' );
171
174
$ controller = [new VariadicController (), 'action ' ];
172
175
173
- self ::$ resolver ->getArguments ($ request , $ controller );
176
+ self ::getResolver () ->getArguments ($ request , $ controller );
174
177
}
175
178
176
179
/**
@@ -179,9 +182,8 @@ public function testGetVariadicArgumentsWithoutArrayInRequest()
179
182
public function testGetArgumentWithoutArray ()
180
183
{
181
184
$ this ->expectException (\InvalidArgumentException::class);
182
- $ factory = new ArgumentMetadataFactory ();
183
185
$ valueResolver = $ this ->createMock (ArgumentValueResolverInterface::class);
184
- $ resolver = new ArgumentResolver ( $ factory , [$ valueResolver ]);
186
+ $ resolver = self :: getResolver ( [$ valueResolver ]);
185
187
186
188
$ valueResolver ->expects ($ this ->any ())->method ('supports ' )->willReturn (true );
187
189
$ valueResolver ->expects ($ this ->any ())->method ('resolve ' )->willReturn ([]);
@@ -199,7 +201,7 @@ public function testIfExceptionIsThrownWhenMissingAnArgument()
199
201
$ request = Request::create ('/ ' );
200
202
$ controller = $ this ->controllerWithFoo (...);
201
203
202
- self ::$ resolver ->getArguments ($ request , $ controller );
204
+ self ::getResolver () ->getArguments ($ request , $ controller );
203
205
}
204
206
205
207
public function testGetNullableArguments ()
@@ -210,7 +212,7 @@ public function testGetNullableArguments()
210
212
$ request ->attributes ->set ('last ' , 'last ' );
211
213
$ controller = [new NullableController (), 'action ' ];
212
214
213
- $ this ->assertEquals (['foo ' , new \stdClass (), 'value ' , 'last ' ], self ::$ resolver ->getArguments ($ request , $ controller ));
215
+ $ this ->assertEquals (['foo ' , new \stdClass (), 'value ' , 'last ' ], self ::getResolver () ->getArguments ($ request , $ controller ));
214
216
}
215
217
216
218
public function testGetNullableArgumentsWithDefaults ()
@@ -219,7 +221,7 @@ public function testGetNullableArgumentsWithDefaults()
219
221
$ request ->attributes ->set ('last ' , 'last ' );
220
222
$ controller = [new NullableController (), 'action ' ];
221
223
222
- $ this ->assertEquals ([null , null , 'value ' , 'last ' ], self ::$ resolver ->getArguments ($ request , $ controller ));
224
+ $ this ->assertEquals ([null , null , 'value ' , 'last ' ], self ::getResolver () ->getArguments ($ request , $ controller ));
223
225
}
224
226
225
227
public function testGetSessionArguments ()
@@ -229,7 +231,7 @@ public function testGetSessionArguments()
229
231
$ request ->setSession ($ session );
230
232
$ controller = $ this ->controllerWithSession (...);
231
233
232
- $ this ->assertEquals ([$ session ], self ::$ resolver ->getArguments ($ request , $ controller ));
234
+ $ this ->assertEquals ([$ session ], self ::getResolver () ->getArguments ($ request , $ controller ));
233
235
}
234
236
235
237
public function testGetSessionArgumentsWithExtendedSession ()
@@ -239,7 +241,7 @@ public function testGetSessionArgumentsWithExtendedSession()
239
241
$ request ->setSession ($ session );
240
242
$ controller = $ this ->controllerWithExtendingSession (...);
241
243
242
- $ this ->assertEquals ([$ session ], self ::$ resolver ->getArguments ($ request , $ controller ));
244
+ $ this ->assertEquals ([$ session ], self ::getResolver () ->getArguments ($ request , $ controller ));
243
245
}
244
246
245
247
public function testGetSessionArgumentsWithInterface ()
@@ -249,7 +251,7 @@ public function testGetSessionArgumentsWithInterface()
249
251
$ request ->setSession ($ session );
250
252
$ controller = $ this ->controllerWithSessionInterface (...);
251
253
252
- $ this ->assertEquals ([$ session ], self ::$ resolver ->getArguments ($ request , $ controller ));
254
+ $ this ->assertEquals ([$ session ], self ::getResolver () ->getArguments ($ request , $ controller ));
253
255
}
254
256
255
257
public function testGetSessionMissMatchWithInterface ()
@@ -260,7 +262,7 @@ public function testGetSessionMissMatchWithInterface()
260
262
$ request ->setSession ($ session );
261
263
$ controller = $ this ->controllerWithExtendingSession (...);
262
264
263
- self ::$ resolver ->getArguments ($ request , $ controller );
265
+ self ::getResolver () ->getArguments ($ request , $ controller );
264
266
}
265
267
266
268
public function testGetSessionMissMatchWithImplementation ()
@@ -271,7 +273,7 @@ public function testGetSessionMissMatchWithImplementation()
271
273
$ request ->setSession ($ session );
272
274
$ controller = $ this ->controllerWithExtendingSession (...);
273
275
274
- self ::$ resolver ->getArguments ($ request , $ controller );
276
+ self ::getResolver () ->getArguments ($ request , $ controller );
275
277
}
276
278
277
279
public function testGetSessionMissMatchOnNull ()
@@ -280,7 +282,51 @@ public function testGetSessionMissMatchOnNull()
280
282
$ request = Request::create ('/ ' );
281
283
$ controller = $ this ->controllerWithExtendingSession (...);
282
284
283
- self ::$ resolver ->getArguments ($ request , $ controller );
285
+ self ::getResolver ()->getArguments ($ request , $ controller );
286
+ }
287
+
288
+ public function testPinnedResolver ()
289
+ {
290
+ $ resolver = self ::getResolver ([], [DefaultValueResolver::class => new DefaultValueResolver ()]);
291
+
292
+ $ request = Request::create ('/ ' );
293
+ $ request ->attributes ->set ('foo ' , 'bar ' );
294
+ $ controller = $ this ->controllerPinningResolver (...);
295
+
296
+ $ this ->assertSame ([1 ], $ resolver ->getArguments ($ request , $ controller ));
297
+ }
298
+
299
+ public function testDisabledResolver ()
300
+ {
301
+ $ resolver = self ::getResolver (namedResolvers: []);
302
+
303
+ $ request = Request::create ('/ ' );
304
+ $ request ->attributes ->set ('foo ' , 'bar ' );
305
+ $ controller = $ this ->controllerDisablingResolver (...);
306
+
307
+ $ this ->assertSame ([1 ], $ resolver ->getArguments ($ request , $ controller ));
308
+ }
309
+
310
+ public function testManyPinnedResolvers ()
311
+ {
312
+ $ resolver = self ::getResolver (namedResolvers: []);
313
+
314
+ $ request = Request::create ('/ ' );
315
+ $ controller = $ this ->controllerPinningManyResolvers (...);
316
+
317
+ $ this ->expectException (\LogicException::class);
318
+ $ resolver ->getArguments ($ request , $ controller );
319
+ }
320
+
321
+ public function testUnknownPinnedResolver ()
322
+ {
323
+ $ resolver = self ::getResolver (namedResolvers: []);
324
+
325
+ $ request = Request::create ('/ ' );
326
+ $ controller = $ this ->controllerPinningUnknownResolver (...);
327
+
328
+ $ this ->expectException (ResolverNotFoundException::class);
329
+ $ resolver ->getArguments ($ request , $ controller );
284
330
}
285
331
286
332
public function __invoke ($ foo , $ bar = null )
@@ -322,6 +368,27 @@ public function controllerWithSessionInterface(SessionInterface $session)
322
368
public function controllerWithExtendingSession (ExtendingSession $ session )
323
369
{
324
370
}
371
+
372
+ public function controllerPinningResolver (#[ValueResolver(DefaultValueResolver::class)] int $ foo = 1 )
373
+ {
374
+ }
375
+
376
+ public function controllerDisablingResolver (#[ValueResolver(RequestAttributeValueResolver::class, disabled: true )] int $ foo = 1 )
377
+ {
378
+ }
379
+
380
+ public function controllerPinningManyResolvers (
381
+ #[ValueResolver(RequestAttributeValueResolver::class)]
382
+ #[ValueResolver(DefaultValueResolver::class)]
383
+ int $ foo
384
+ ) {
385
+ }
386
+
387
+ public function controllerPinningUnknownResolver (
388
+ #[ValueResolver('foo ' )]
389
+ int $ bar
390
+ ) {
391
+ }
325
392
}
326
393
327
394
function controller_function ($ foo , $ foobar )
0 commit comments