ca121c732711e51aaa2c412c8c10d72ef1c8e550
[yaffs-website] / vendor / symfony / http-kernel / Tests / DependencyInjection / RegisterControllerArgumentLocatorsPassTest.php
1 <?php
2
3 /*
4  * This file is part of the Symfony package.
5  *
6  * (c) Fabien Potencier <fabien@symfony.com>
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 Symfony\Component\HttpKernel\Tests\DependencyInjection;
13
14 use PHPUnit\Framework\TestCase;
15 use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
16 use Symfony\Component\DependencyInjection\ChildDefinition;
17 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
18 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
19 use Symfony\Component\DependencyInjection\ContainerBuilder;
20 use Symfony\Component\DependencyInjection\ContainerInterface;
21 use Symfony\Component\DependencyInjection\Reference;
22 use Symfony\Component\DependencyInjection\ServiceLocator;
23 use Symfony\Component\DependencyInjection\TypedReference;
24 use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
25
26 class RegisterControllerArgumentLocatorsPassTest extends TestCase
27 {
28     /**
29      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
30      * @expectedExceptionMessage Class "Symfony\Component\HttpKernel\Tests\DependencyInjection\NotFound" used for service "foo" cannot be found.
31      */
32     public function testInvalidClass()
33     {
34         $container = new ContainerBuilder();
35         $container->register('argument_resolver.service')->addArgument(array());
36
37         $container->register('foo', NotFound::class)
38             ->addTag('controller.service_arguments')
39         ;
40
41         $pass = new RegisterControllerArgumentLocatorsPass();
42         $pass->process($container);
43     }
44
45     /**
46      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
47      * @expectedExceptionMessage Missing "action" attribute on tag "controller.service_arguments" {"argument":"bar"} for service "foo".
48      */
49     public function testNoAction()
50     {
51         $container = new ContainerBuilder();
52         $container->register('argument_resolver.service')->addArgument(array());
53
54         $container->register('foo', RegisterTestController::class)
55             ->addTag('controller.service_arguments', array('argument' => 'bar'))
56         ;
57
58         $pass = new RegisterControllerArgumentLocatorsPass();
59         $pass->process($container);
60     }
61
62     /**
63      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
64      * @expectedExceptionMessage Missing "argument" attribute on tag "controller.service_arguments" {"action":"fooAction"} for service "foo".
65      */
66     public function testNoArgument()
67     {
68         $container = new ContainerBuilder();
69         $container->register('argument_resolver.service')->addArgument(array());
70
71         $container->register('foo', RegisterTestController::class)
72             ->addTag('controller.service_arguments', array('action' => 'fooAction'))
73         ;
74
75         $pass = new RegisterControllerArgumentLocatorsPass();
76         $pass->process($container);
77     }
78
79     /**
80      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
81      * @expectedExceptionMessage Missing "id" attribute on tag "controller.service_arguments" {"action":"fooAction","argument":"bar"} for service "foo".
82      */
83     public function testNoService()
84     {
85         $container = new ContainerBuilder();
86         $container->register('argument_resolver.service')->addArgument(array());
87
88         $container->register('foo', RegisterTestController::class)
89             ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar'))
90         ;
91
92         $pass = new RegisterControllerArgumentLocatorsPass();
93         $pass->process($container);
94     }
95
96     /**
97      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
98      * @expectedExceptionMessage Invalid "action" attribute on tag "controller.service_arguments" for service "foo": no public "barAction()" method found on class "Symfony\Component\HttpKernel\Tests\DependencyInjection\RegisterTestController".
99      */
100     public function testInvalidMethod()
101     {
102         $container = new ContainerBuilder();
103         $container->register('argument_resolver.service')->addArgument(array());
104
105         $container->register('foo', RegisterTestController::class)
106             ->addTag('controller.service_arguments', array('action' => 'barAction', 'argument' => 'bar', 'id' => 'bar_service'))
107         ;
108
109         $pass = new RegisterControllerArgumentLocatorsPass();
110         $pass->process($container);
111     }
112
113     /**
114      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
115      * @expectedExceptionMessage Invalid "controller.service_arguments" tag for service "foo": method "fooAction()" has no "baz" argument on class "Symfony\Component\HttpKernel\Tests\DependencyInjection\RegisterTestController".
116      */
117     public function testInvalidArgument()
118     {
119         $container = new ContainerBuilder();
120         $container->register('argument_resolver.service')->addArgument(array());
121
122         $container->register('foo', RegisterTestController::class)
123             ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'baz', 'id' => 'bar'))
124         ;
125
126         $pass = new RegisterControllerArgumentLocatorsPass();
127         $pass->process($container);
128     }
129
130     public function testAllActions()
131     {
132         $container = new ContainerBuilder();
133         $resolver = $container->register('argument_resolver.service')->addArgument(array());
134
135         $container->register('foo', RegisterTestController::class)
136             ->addTag('controller.service_arguments')
137         ;
138
139         $pass = new RegisterControllerArgumentLocatorsPass();
140         $pass->process($container);
141
142         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
143
144         $this->assertEquals(array('foo:fooAction'), array_keys($locator));
145         $this->assertInstanceof(ServiceClosureArgument::class, $locator['foo:fooAction']);
146
147         $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]);
148
149         $this->assertSame(ServiceLocator::class, $locator->getClass());
150         $this->assertFalse($locator->isPublic());
151
152         $expected = array('bar' => new ServiceClosureArgument(new TypedReference(ControllerDummy::class, ControllerDummy::class, RegisterTestController::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)));
153         $this->assertEquals($expected, $locator->getArgument(0));
154     }
155
156     public function testExplicitArgument()
157     {
158         $container = new ContainerBuilder();
159         $resolver = $container->register('argument_resolver.service')->addArgument(array());
160
161         $container->register('foo', RegisterTestController::class)
162             ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar', 'id' => 'bar'))
163             ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar', 'id' => 'baz')) // should be ignored, the first wins
164         ;
165
166         $pass = new RegisterControllerArgumentLocatorsPass();
167         $pass->process($container);
168
169         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
170         $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]);
171
172         $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, RegisterTestController::class)));
173         $this->assertEquals($expected, $locator->getArgument(0));
174     }
175
176     public function testOptionalArgument()
177     {
178         $container = new ContainerBuilder();
179         $resolver = $container->register('argument_resolver.service')->addArgument(array());
180
181         $container->register('foo', RegisterTestController::class)
182             ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar', 'id' => '?bar'))
183         ;
184
185         $pass = new RegisterControllerArgumentLocatorsPass();
186         $pass->process($container);
187
188         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
189         $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]);
190
191         $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, RegisterTestController::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)));
192         $this->assertEquals($expected, $locator->getArgument(0));
193     }
194
195     public function testSkipSetContainer()
196     {
197         $container = new ContainerBuilder();
198         $resolver = $container->register('argument_resolver.service')->addArgument(array());
199
200         $container->register('foo', ContainerAwareRegisterTestController::class)
201             ->addTag('controller.service_arguments');
202
203         $pass = new RegisterControllerArgumentLocatorsPass();
204         $pass->process($container);
205
206         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
207         $this->assertSame(array('foo:fooAction'), array_keys($locator));
208     }
209
210     /**
211      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
212      * @expectedExceptionMessage Cannot determine controller argument for "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClassController::fooAction()": the $nonExistent argument is type-hinted with the non-existent class or interface: "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClass". Did you forget to add a use statement?
213      */
214     public function testExceptionOnNonExistentTypeHint()
215     {
216         $container = new ContainerBuilder();
217         $container->register('argument_resolver.service')->addArgument(array());
218
219         $container->register('foo', NonExistentClassController::class)
220             ->addTag('controller.service_arguments');
221
222         $pass = new RegisterControllerArgumentLocatorsPass();
223         $pass->process($container);
224     }
225
226     /**
227      * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
228      * @expectedExceptionMessage Cannot determine controller argument for "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClassDifferentNamespaceController::fooAction()": the $nonExistent argument is type-hinted with the non-existent class or interface: "Acme\NonExistentClass".
229      */
230     public function testExceptionOnNonExistentTypeHintDifferentNamespace()
231     {
232         $container = new ContainerBuilder();
233         $container->register('argument_resolver.service')->addArgument(array());
234
235         $container->register('foo', NonExistentClassDifferentNamespaceController::class)
236             ->addTag('controller.service_arguments');
237
238         $pass = new RegisterControllerArgumentLocatorsPass();
239         $pass->process($container);
240     }
241
242     public function testNoExceptionOnNonExistentTypeHintOptionalArg()
243     {
244         $container = new ContainerBuilder();
245         $resolver = $container->register('argument_resolver.service')->addArgument(array());
246
247         $container->register('foo', NonExistentClassOptionalController::class)
248             ->addTag('controller.service_arguments');
249
250         $pass = new RegisterControllerArgumentLocatorsPass();
251         $pass->process($container);
252
253         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
254         $this->assertSame(array('foo:barAction', 'foo:fooAction'), array_keys($locator));
255     }
256
257     public function testArgumentWithNoTypeHintIsOk()
258     {
259         $container = new ContainerBuilder();
260         $resolver = $container->register('argument_resolver.service')->addArgument(array());
261
262         $container->register('foo', ArgumentWithoutTypeController::class)
263             ->addTag('controller.service_arguments');
264
265         $pass = new RegisterControllerArgumentLocatorsPass();
266         $pass->process($container);
267
268         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
269         $this->assertEmpty(array_keys($locator));
270     }
271
272     public function testControllersAreMadePublic()
273     {
274         $container = new ContainerBuilder();
275         $resolver = $container->register('argument_resolver.service')->addArgument(array());
276
277         $container->register('foo', ArgumentWithoutTypeController::class)
278             ->setPublic(false)
279             ->addTag('controller.service_arguments');
280
281         $pass = new RegisterControllerArgumentLocatorsPass();
282         $pass->process($container);
283
284         $this->assertTrue($container->getDefinition('foo')->isPublic());
285     }
286
287     /**
288      * @dataProvider provideBindings
289      */
290     public function testBindings($bindingName)
291     {
292         $container = new ContainerBuilder();
293         $resolver = $container->register('argument_resolver.service')->addArgument(array());
294
295         $container->register('foo', RegisterTestController::class)
296             ->setBindings(array($bindingName => new Reference('foo')))
297             ->addTag('controller.service_arguments');
298
299         $pass = new RegisterControllerArgumentLocatorsPass();
300         $pass->process($container);
301
302         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
303
304         $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]);
305
306         $expected = array('bar' => new ServiceClosureArgument(new Reference('foo')));
307         $this->assertEquals($expected, $locator->getArgument(0));
308     }
309
310     public function provideBindings()
311     {
312         return array(array(ControllerDummy::class), array('$bar'));
313     }
314
315     public function testDoNotBindScalarValueToControllerArgument()
316     {
317         $container = new ContainerBuilder();
318         $resolver = $container->register('argument_resolver.service')->addArgument(array());
319
320         $container->register('foo', ArgumentWithoutTypeController::class)
321             ->setBindings(array('$someArg' => '%foo%'))
322             ->addTag('controller.service_arguments');
323
324         $pass = new RegisterControllerArgumentLocatorsPass();
325         $pass->process($container);
326
327         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
328         $this->assertEmpty($locator);
329     }
330
331     public function testBindingsOnChildDefinitions()
332     {
333         $container = new ContainerBuilder();
334         $resolver = $container->register('argument_resolver.service')->addArgument(array());
335
336         $container->register('parent', ArgumentWithoutTypeController::class);
337
338         $container->setDefinition('child', (new ChildDefinition('parent'))
339             ->setBindings(array('$someArg' => new Reference('parent')))
340             ->addTag('controller.service_arguments')
341         );
342
343         $pass = new RegisterControllerArgumentLocatorsPass();
344         $pass->process($container);
345
346         $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
347         $this->assertInstanceOf(ServiceClosureArgument::class, $locator['child:fooAction']);
348
349         $locator = $container->getDefinition((string) $locator['child:fooAction']->getValues()[0])->getArgument(0);
350         $this->assertInstanceOf(ServiceClosureArgument::class, $locator['someArg']);
351         $this->assertEquals(new Reference('parent'), $locator['someArg']->getValues()[0]);
352     }
353 }
354
355 class RegisterTestController
356 {
357     public function __construct(ControllerDummy $bar)
358     {
359     }
360
361     public function fooAction(ControllerDummy $bar)
362     {
363     }
364
365     protected function barAction(ControllerDummy $bar)
366     {
367     }
368 }
369
370 class ContainerAwareRegisterTestController implements ContainerAwareInterface
371 {
372     use ContainerAwareTrait;
373
374     public function fooAction(ControllerDummy $bar)
375     {
376     }
377 }
378
379 class ControllerDummy
380 {
381 }
382
383 class NonExistentClassController
384 {
385     public function fooAction(NonExistentClass $nonExistent)
386     {
387     }
388 }
389
390 class NonExistentClassDifferentNamespaceController
391 {
392     public function fooAction(\Acme\NonExistentClass $nonExistent)
393     {
394     }
395 }
396
397 class NonExistentClassOptionalController
398 {
399     public function fooAction(NonExistentClass $nonExistent = null)
400     {
401     }
402
403     public function barAction(NonExistentClass $nonExistent = null, $bar)
404     {
405     }
406 }
407
408 class ArgumentWithoutTypeController
409 {
410     public function fooAction($someArg)
411     {
412     }
413 }