0019123b6819c6b1c6dd964dc854f250fbb9c14e
[yaffs-website] / vendor / symfony / http-kernel / Tests / Controller / ContainerControllerResolverTest.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\Controller;
13
14 use Psr\Container\ContainerInterface;
15 use Psr\Log\LoggerInterface;
16 use Symfony\Component\Debug\ErrorHandler;
17 use Symfony\Component\DependencyInjection\Container;
18 use Symfony\Component\HttpFoundation\Request;
19 use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
20
21 class ContainerControllerResolverTest extends ControllerResolverTest
22 {
23     public function testGetControllerService()
24     {
25         $container = $this->createMockContainer();
26         $container->expects($this->once())
27             ->method('has')
28             ->with('foo')
29             ->will($this->returnValue(true));
30         $container->expects($this->once())
31             ->method('get')
32             ->with('foo')
33             ->will($this->returnValue($this))
34         ;
35
36         $resolver = $this->createControllerResolver(null, $container);
37         $request = Request::create('/');
38         $request->attributes->set('_controller', 'foo:controllerMethod1');
39
40         $controller = $resolver->getController($request);
41
42         $this->assertInstanceOf(get_class($this), $controller[0]);
43         $this->assertSame('controllerMethod1', $controller[1]);
44     }
45
46     public function testGetControllerInvokableService()
47     {
48         $invokableController = new InvokableController('bar');
49
50         $container = $this->createMockContainer();
51         $container->expects($this->once())
52             ->method('has')
53             ->with('foo')
54             ->will($this->returnValue(true))
55         ;
56         $container->expects($this->once())
57             ->method('get')
58             ->with('foo')
59             ->will($this->returnValue($invokableController))
60         ;
61
62         $resolver = $this->createControllerResolver(null, $container);
63         $request = Request::create('/');
64         $request->attributes->set('_controller', 'foo');
65
66         $controller = $resolver->getController($request);
67
68         $this->assertEquals($invokableController, $controller);
69     }
70
71     public function testGetControllerInvokableServiceWithClassNameAsName()
72     {
73         $invokableController = new InvokableController('bar');
74         $className = __NAMESPACE__.'\InvokableController';
75
76         $container = $this->createMockContainer();
77         $container->expects($this->once())
78             ->method('has')
79             ->with($className)
80             ->will($this->returnValue(true))
81         ;
82         $container->expects($this->once())
83             ->method('get')
84             ->with($className)
85             ->will($this->returnValue($invokableController))
86         ;
87
88         $resolver = $this->createControllerResolver(null, $container);
89         $request = Request::create('/');
90         $request->attributes->set('_controller', $className);
91
92         $controller = $resolver->getController($request);
93
94         $this->assertEquals($invokableController, $controller);
95     }
96
97     public function testNonInstantiableController()
98     {
99         $container = $this->createMockContainer();
100         $container->expects($this->once())
101             ->method('has')
102             ->with(NonInstantiableController::class)
103             ->will($this->returnValue(false))
104         ;
105
106         $resolver = $this->createControllerResolver(null, $container);
107         $request = Request::create('/');
108         $request->attributes->set('_controller', array(NonInstantiableController::class, 'action'));
109
110         $controller = $resolver->getController($request);
111
112         $this->assertSame(array(NonInstantiableController::class, 'action'), $controller);
113     }
114
115     /**
116      * @expectedException \LogicException
117      * @expectedExceptionMessage Controller "Symfony\Component\HttpKernel\Tests\Controller\ImpossibleConstructController" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?
118      */
119     public function testNonConstructController()
120     {
121         $container = $this->getMockBuilder(Container::class)->getMock();
122         $container->expects($this->at(0))
123             ->method('has')
124             ->with(ImpossibleConstructController::class)
125             ->will($this->returnValue(true))
126         ;
127
128         $container->expects($this->at(1))
129             ->method('has')
130             ->with(ImpossibleConstructController::class)
131             ->will($this->returnValue(false))
132         ;
133
134         $container->expects($this->atLeastOnce())
135             ->method('getRemovedIds')
136             ->with()
137             ->will($this->returnValue(array(ImpossibleConstructController::class => true)))
138         ;
139
140         $resolver = $this->createControllerResolver(null, $container);
141         $request = Request::create('/');
142         $request->attributes->set('_controller', array(ImpossibleConstructController::class, 'action'));
143
144         if (\PHP_VERSION_ID < 70100) {
145             ErrorHandler::register();
146             try {
147                 $resolver->getController($request);
148             } finally {
149                 restore_error_handler();
150                 restore_exception_handler();
151             }
152         } else {
153             $resolver->getController($request);
154         }
155     }
156
157     public function testNonInstantiableControllerWithCorrespondingService()
158     {
159         $service = new \stdClass();
160
161         $container = $this->createMockContainer();
162         $container->expects($this->atLeastOnce())
163             ->method('has')
164             ->with(NonInstantiableController::class)
165             ->will($this->returnValue(true))
166         ;
167         $container->expects($this->atLeastOnce())
168             ->method('get')
169             ->with(NonInstantiableController::class)
170             ->will($this->returnValue($service))
171         ;
172
173         $resolver = $this->createControllerResolver(null, $container);
174         $request = Request::create('/');
175         $request->attributes->set('_controller', array(NonInstantiableController::class, 'action'));
176
177         $controller = $resolver->getController($request);
178
179         $this->assertSame(array($service, 'action'), $controller);
180     }
181
182     /**
183      * @expectedException \LogicException
184      * @expectedExceptionMessage Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?
185      */
186     public function testExceptionWhenUsingRemovedControllerService()
187     {
188         $container = $this->getMockBuilder(Container::class)->getMock();
189         $container->expects($this->at(0))
190             ->method('has')
191             ->with('app.my_controller')
192             ->will($this->returnValue(false))
193         ;
194
195         $container->expects($this->atLeastOnce())
196             ->method('getRemovedIds')
197             ->with()
198             ->will($this->returnValue(array('app.my_controller' => true)))
199         ;
200
201         $resolver = $this->createControllerResolver(null, $container);
202
203         $request = Request::create('/');
204         $request->attributes->set('_controller', 'app.my_controller');
205         $resolver->getController($request);
206     }
207
208     /**
209      * @expectedException \LogicException
210      * @expectedExceptionMessage Controller "app.my_controller" cannot be called without a method name. Did you forget an "__invoke" method?
211      */
212     public function testExceptionWhenUsingControllerWithoutAnInvokeMethod()
213     {
214         $container = $this->getMockBuilder(Container::class)->getMock();
215         $container->expects($this->once())
216             ->method('has')
217             ->with('app.my_controller')
218             ->will($this->returnValue(true))
219         ;
220         $container->expects($this->once())
221             ->method('get')
222             ->with('app.my_controller')
223             ->will($this->returnValue(new ImpossibleConstructController('toto', 'controller')))
224         ;
225
226         $resolver = $this->createControllerResolver(null, $container);
227
228         $request = Request::create('/');
229         $request->attributes->set('_controller', 'app.my_controller');
230         $resolver->getController($request);
231     }
232
233     /**
234      * @dataProvider getUndefinedControllers
235      */
236     public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null)
237     {
238         // All this logic needs to be duplicated, since calling parent::testGetControllerOnNonUndefinedFunction will override the expected excetion and not use the regex
239         $resolver = $this->createControllerResolver();
240         if (method_exists($this, 'expectException')) {
241             $this->expectException($exceptionName);
242             $this->expectExceptionMessageRegExp($exceptionMessage);
243         } else {
244             $this->setExpectedExceptionRegExp($exceptionName, $exceptionMessage);
245         }
246
247         $request = Request::create('/');
248         $request->attributes->set('_controller', $controller);
249         $resolver->getController($request);
250     }
251
252     public function getUndefinedControllers()
253     {
254         return array(
255             array('foo', \LogicException::class, '/Controller not found: service "foo" does not exist\./'),
256             array('oof::bar', \InvalidArgumentException::class, '/Class "oof" does not exist\./'),
257             array('stdClass', \LogicException::class, '/Controller not found: service "stdClass" does not exist\./'),
258             array(
259                 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar',
260                 \InvalidArgumentException::class,
261                 '/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/',
262             ),
263         );
264     }
265
266     protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null)
267     {
268         if (!$container) {
269             $container = $this->createMockContainer();
270         }
271
272         return new ContainerControllerResolver($container, $logger);
273     }
274
275     protected function createMockContainer()
276     {
277         return $this->getMockBuilder(ContainerInterface::class)->getMock();
278     }
279 }
280
281 class InvokableController
282 {
283     public function __construct($bar) // mandatory argument to prevent automatic instantiation
284     {
285     }
286
287     public function __invoke()
288     {
289     }
290 }
291
292 abstract class NonInstantiableController
293 {
294     public static function action()
295     {
296     }
297 }
298
299 class ImpossibleConstructController
300 {
301     public function __construct($toto, $controller)
302     {
303     }
304
305     public function action()
306     {
307     }
308 }