Skip to content

Commit b1173f3

Browse files
author
Amrouche Hamza
committed
[HttpKernel] Add a better error messages when passing a private or non-tagged controller
1 parent 1f14f4d commit b1173f3

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

src/Symfony/Component/HttpKernel/Controller/ContainerControllerResolver.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Psr\Container\ContainerInterface;
1515
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\DependencyInjection\Container;
1617
use Symfony\Component\HttpFoundation\Request;
1718

1819
/**
@@ -86,6 +87,17 @@ protected function instantiateController($class)
8687
return $this->container->get($class);
8788
}
8889

89-
return parent::instantiateController($class);
90+
try {
91+
return parent::instantiateController($class);
92+
} catch (\ArgumentCountError $e) {
93+
} catch (\ErrorException $e) {
94+
} catch (\TypeError $e) {
95+
}
96+
97+
if ($this->container instanceof Container && in_array($class, $this->container->getRemovedIds(), true)) {
98+
throw new \LogicException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $class), 0, $e);
99+
}
100+
101+
throw $e;
90102
}
91103
}

src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
use Psr\Container\ContainerInterface;
1515
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\Debug\ErrorHandler;
17+
use Symfony\Component\DependencyInjection\Container;
1618
use Symfony\Component\HttpFoundation\Request;
1719
use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
1820

@@ -106,6 +108,48 @@ public function testNonInstantiableController()
106108
$this->assertSame(array(NonInstantiableController::class, 'action'), $controller);
107109
}
108110

111+
/**
112+
* @expectedException \LogicException
113+
* @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"?
114+
*/
115+
public function testNonConstructController()
116+
{
117+
$container = $this->getMockBuilder(Container::class)->getMock();
118+
$container->expects($this->at(0))
119+
->method('has')
120+
->with(ImpossibleConstructController::class)
121+
->will($this->returnValue(true))
122+
;
123+
124+
$container->expects($this->at(1))
125+
->method('has')
126+
->with(ImpossibleConstructController::class)
127+
->will($this->returnValue(false))
128+
;
129+
130+
$container->expects($this->atLeastOnce())
131+
->method('getRemovedIds')
132+
->with()
133+
->will($this->returnValue(array(ImpossibleConstructController::class)))
134+
;
135+
136+
$resolver = $this->createControllerResolver(null, $container);
137+
$request = Request::create('/');
138+
$request->attributes->set('_controller', array(ImpossibleConstructController::class, 'action'));
139+
140+
if (\PHP_VERSION_ID < 70100) {
141+
ErrorHandler::register();
142+
try {
143+
$resolver->getController($request);
144+
} finally {
145+
restore_error_handler();
146+
restore_exception_handler();
147+
}
148+
} else {
149+
$resolver->getController($request);
150+
}
151+
}
152+
109153
public function testNonInstantiableControllerWithCorrespondingService()
110154
{
111155
$service = new \stdClass();
@@ -196,3 +240,14 @@ public static function action()
196240
{
197241
}
198242
}
243+
244+
class ImpossibleConstructController
245+
{
246+
public function __construct($toto, $controller)
247+
{
248+
}
249+
250+
public function action()
251+
{
252+
}
253+
}

0 commit comments

Comments
 (0)