[HttpKernel] Add a better error messages when passing a private or non-tagged controller

This commit is contained in:
Amrouche Hamza 2017-11-29 08:28:02 +01:00
parent 1f14f4d836
commit b1173f3ea7
No known key found for this signature in database
GPG Key ID: 6968F2785ED4F012
2 changed files with 68 additions and 1 deletions

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Controller;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpFoundation\Request;
/**
@ -86,6 +87,17 @@ class ContainerControllerResolver extends ControllerResolver
return $this->container->get($class);
}
return parent::instantiateController($class);
try {
return parent::instantiateController($class);
} catch (\ArgumentCountError $e) {
} catch (\ErrorException $e) {
} catch (\TypeError $e) {
}
if ($this->container instanceof Container && in_array($class, $this->container->getRemovedIds(), true)) {
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);
}
throw $e;
}
}

View File

@ -13,6 +13,8 @@ namespace Symfony\Component\HttpKernel\Tests\Controller;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
@ -106,6 +108,48 @@ class ContainerControllerResolverTest extends ControllerResolverTest
$this->assertSame(array(NonInstantiableController::class, 'action'), $controller);
}
/**
* @expectedException \LogicException
* @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"?
*/
public function testNonConstructController()
{
$container = $this->getMockBuilder(Container::class)->getMock();
$container->expects($this->at(0))
->method('has')
->with(ImpossibleConstructController::class)
->will($this->returnValue(true))
;
$container->expects($this->at(1))
->method('has')
->with(ImpossibleConstructController::class)
->will($this->returnValue(false))
;
$container->expects($this->atLeastOnce())
->method('getRemovedIds')
->with()
->will($this->returnValue(array(ImpossibleConstructController::class)))
;
$resolver = $this->createControllerResolver(null, $container);
$request = Request::create('/');
$request->attributes->set('_controller', array(ImpossibleConstructController::class, 'action'));
if (\PHP_VERSION_ID < 70100) {
ErrorHandler::register();
try {
$resolver->getController($request);
} finally {
restore_error_handler();
restore_exception_handler();
}
} else {
$resolver->getController($request);
}
}
public function testNonInstantiableControllerWithCorrespondingService()
{
$service = new \stdClass();
@ -196,3 +240,14 @@ abstract class NonInstantiableController
{
}
}
class ImpossibleConstructController
{
public function __construct($toto, $controller)
{
}
public function action()
{
}
}