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