diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index e2e8a84163859..7685c6472aeb5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -153,6 +153,10 @@ public function load(array $configs, ContainerBuilder $container) $definition->replaceArgument(2, E_COMPILE_ERROR | E_PARSE | E_ERROR | E_CORE_ERROR); } + if (interface_exists('Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface')) { + $loader->load('psr-http-message.xml'); + } + $this->addClassesToCompile(array( 'Symfony\\Component\\Config\\FileLocator', diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 499f39c6c95c0..6a1c8baf7f9dd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -36,6 +36,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\HttpKernel\DependencyInjection\RegisterArgumentResolversPass; /** * Bundle. @@ -88,6 +89,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new TranslationDumperPass()); $container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new SerializerPass()); + $container->addCompilerPass(new RegisterArgumentResolversPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/psr-http-message.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/psr-http-message.xml new file mode 100644 index 0000000000000..ffb2eab4f7e77 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/psr-http-message.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 2021505726fef..f816ce38d37e5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -25,6 +25,7 @@ + false diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml index 9b2f3cb3a4373..74e8899cb36ab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml @@ -25,6 +25,16 @@ + + + + + + + + + + %kernel.charset% diff --git a/src/Symfony/Bundle/SecurityBundle/ArgumentResolver/UserArgumentResolver.php b/src/Symfony/Bundle/SecurityBundle/ArgumentResolver/UserArgumentResolver.php new file mode 100644 index 0000000000000..6c0c885020d07 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/ArgumentResolver/UserArgumentResolver.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ArgumentResolverInterface; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; + +/** + * Resolves a typehint for UserInterface in a controller to the current user. + * + * @author Wouter J + */ +class UserArgumentResolver implements ArgumentResolverInterface +{ + /** + * @var TokenStorageInterface + */ + private $tokenStorage; + + public function __construct(TokenStorageInterface $tokenStorage) + { + $this->tokenStorage = $tokenStorage; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, \ReflectionParameter $parameter) + { + $class = $parameter->getClass(); + $userInterface = 'Symfony\Component\Security\Core\User\UserInterface'; + $userImplementation = 'Symfony\Component\Security\Core\User\User'; + + return null !== $class && ($userInterface === $class->getName() || $userImplementation === $class->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, \ReflectionParameter $parameter) + { + if (null === $token = $this->tokenStorage->getToken()) { + return; + } + + if (!is_object($user = $token->getUser())) { + // e.g. anonymous authentication + return; + } + + return $user; + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index b7c1407c1cc56..ad08b4bd05726 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -50,6 +50,12 @@ + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/ArgumentResolver/UserArgumentResolverTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/ArgumentResolver/UserArgumentResolverTest.php new file mode 100644 index 0000000000000..608065ef101eb --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/ArgumentResolver/UserArgumentResolverTest.php @@ -0,0 +1,96 @@ + + */ +class UserArgumentResolverTest extends \PHPUnit_Framework_TestCase +{ + private $resolver; + private $tokenStorage; + + protected function setUp() + { + $this->tokenStorage = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface'); + $this->resolver = new UserArgumentResolver($this->tokenStorage); + } + + /** + * @dataProvider provideClasses + */ + public function testSupports($class, $supported = true) + { + $this->assertEquals($supported, $this->resolver->supports($this->getRequestMock(), $this->getReflectionParameterMock($class))); + } + + public function provideClasses() + { + return array( + array('Symfony\Component\Security\Core\User\UserInterface'), + array('Symfony\Component\Security\Core\User\User'), + array('Symfony\Bundle\SecurityBundle\Tests\ArgumentResolver\UserFixture', false), + array('\stdClass', false), + ); + } + + public function testResolvesToNullWhenNoUserIsAvailable() + { + $this->tokenStorage->expects($this->any())->method('getToken')->willReturn(null); + + $this->assertNull($this->resolver->resolve($this->getRequestMock(), $this->getReflectionParameterMock())); + } + + public function testResolvesToNullWhenUserIsAnonymous() + { + $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); + $token->expects($this->any())->method('getUser')->willReturn('anon.'); + + $this->tokenStorage->expects($this->any())->method('getToken')->willReturn($token); + + $this->assertNull($this->resolver->resolve($this->getRequestMock(), $this->getReflectionParameterMock())); + } + + public function testResolvesToUser() + { + $user = $this->getMock('Symfony\component\Security\Core\User\User'); + + $token = $this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'); + $token->expects($this->any())->method('getUser')->willReturn($user); + + $this->tokenStorage->expects($this->any())->method('getToken')->willReturn($token); + + $this->assertEquals($user, $this->resolver->resolve($this->getRequestMock(), $this->getReflectionParameterMock())); + } + + private function getRequestMock() + { + return $this->getMock('Symfony\Component\HttpFoundation\Request'); + } + + private function getReflectionParameterMock($class = null) + { + $reflectionParameter = $this->getMockBuilder('\ReflectionParameter')->disableOriginalConstructor()->getMock(); + + if (null !== $class) { + $reflectionClass = $this->getMockBuilder('\ReflectionClass')->disableOriginalConstructor()->getMock(); + $reflectionClass->expects($this->any())->method('getName')->willReturn($class); + $reflectionParameter->expects($this->any())->method('getClass')->willReturn($reflectionClass); + } + + return $reflectionParameter; + } +} + +class UserFixture implements UserInterface +{ + public function getRoles() {} + public function getPassword() {} + public function getSalt() {} + public function getUsername() {} + public function eraseCredentials() {} +} diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index ad27886ac8738..e8d60ff309a10 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +2.8.0 +----- + + * added argument resolvers + * deprecated `Symfony\Component\HttpKernel\Controller\ControllerResolver::getArguments()` and `doGetArguments()` in favor of argument resolvers + 2.7.0 ----- diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ArgumentResolverInterface.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ArgumentResolverInterface.php new file mode 100644 index 0000000000000..9fa90de09e360 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/ArgumentResolverInterface.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; + +/** + * An ArgumentResolverInterface implementation resolves the arguments of + * controllers. + * + * @author Wouter J + */ +interface ArgumentResolverInterface +{ + /** + * Checks if the current pameter can be esolved by this argument + * resolver. + * + * @param Request $request + * @param \ReflectionParameter $parameter + * + * @return bool + */ + public function supports(Request $request, \ReflectionParameter $parameter); + + /** + * Resolves the current parameter into an argument. + * + * @param Request $request + * @param \ReflectionParameter $parameter + * + * @return mixed The resolved argument + */ + public function resolve(Request $request, \ReflectionParameter $parameter); +} diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/PsrServerRequestArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/PsrServerRequestArgumentResolver.php new file mode 100644 index 0000000000000..35233a08422b6 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/PsrServerRequestArgumentResolver.php @@ -0,0 +1,52 @@ + + * @author Wouter J + */ +class PsrServerRequestArgumentResolver implements ArgumentResolverInterface +{ + /** + * @var array + */ + private static $supportedTypes = array( + 'Psr\Http\Message\ServerRequestInterface' => true, + 'Psr\Http\Message\RequestInterface' => true, + 'Psr\Http\Message\MessageInterface' => true, + ); + + /** + * @var HttpMessageFactoryInterface + */ + private $httpMessageFactory; + + public function __construct(HttpMessageFactoryInterface $httpMessageFactory) + { + $this->httpMessageFactory = $httpMessageFactory; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, \ReflectionParameter $parameter) + { + $class = $parameter->getClass(); + + return null !== $class && isset(self::$supportedTypes[$class->getName()]); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, \ReflectionParameter $parameter) + { + return $this->httpMessageFactory->createRequest($request); + } +} diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php new file mode 100644 index 0000000000000..f80d7b4ce31a2 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestArgumentResolver.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; + +/** + * Resolves arguments typehinting for the HttpFoundation Request object. + * + * @author Wouter J + */ +class RequestArgumentResolver implements ArgumentResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, \ReflectionParameter $parameter) + { + $class = $parameter->getClass(); + + return $class && $class->isInstance($request); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, \ReflectionParameter $parameter) + { + return $request; + } +} diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php new file mode 100644 index 0000000000000..e6c23ceec5d7c --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver/RequestAttributesArgumentResolver.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; + +/** + * Resolves arguments which names are equal to the name of a request attribute. + * + * @author Wouter J + */ +class RequestAttributesArgumentResolver implements ArgumentResolverInterface +{ + /** + * {@inheritdoc} + */ + public function supports(Request $request, \ReflectionParameter $parameter) + { + return $request->attributes->has($parameter->getName()); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, \ReflectionParameter $parameter) + { + return $request->attributes->get($parameter->getName()); + } +} diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php new file mode 100644 index 0000000000000..46bfb003da7ae --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolverManager.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ArgumentResolverInterface; + +/** + * The ArgumentResolverManager chains over the registered argument resolvers to + * resolve all controller arguments. + * + * @author Wouter J + */ +class ArgumentResolverManager +{ + /** + * @var ArgumentResolverInterface[] + */ + private $resolvers; + + /** + * @param ArgumentResolverInterface[] $resolvers + */ + public function __construct(array $resolvers = array()) + { + $this->resolvers = $resolvers; + } + + /** + * Adds an argument resolver to the chain. + * + * The order in which the resolvers will be chained is equal + * to the order in which this method is called. + * + * @param ArgumentResolverInterface $resolver + */ + public function add(ArgumentResolverInterface $resolver) + { + $this->resolvers[] = $resolver; + } + + /** + * Resolves the constructor arguments of the passed controller. + * + * @param Request $request + * @param callable $controller + * + * @return array + */ + public function getArguments(Request $request, $controller) + { + if (!is_callable($controller)) { + throw new \InvalidArgumentException(sprintf('Expected a callable as second parameter, got "%s".', is_object($controller) ? get_class($controller) : gettype($controller))); + } + + if (is_array($controller)) { + $controllerReflection = new \ReflectionMethod($controller[0], $controller[1]); + } elseif (is_object($controller) && !$controller instanceof \Closure) { + $controllerReflection = new \ReflectionObject($controller); + $controllerReflection = $controllerReflection->getMethod('__invoke'); + } else { + $controllerReflection = new \ReflectionFunction($controller); + } + + $parameters = $controllerReflection->getParameters(); + $arguments = array(); + + foreach ($parameters as $parameter) { + foreach ($this->resolvers as $argumentResolver) { + if ($argumentResolver->supports($request, $parameter)) { + $arguments[] = $argumentResolver->resolve($request, $parameter); + continue 2; + } + } + + if ($parameter->isDefaultValueAvailable()) { + $arguments[] = $parameter->getDefaultValue(); + } else { + if (is_array($controller)) { + $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); + } elseif (is_object($controller)) { + $repr = get_class($controller); + } else { + $repr = $controller; + } + + throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value and none of the argument resolvers could resolve its value).', $repr, $parameter->name)); + } + } + + return $arguments; + } +} diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 94df05eee415f..f1dfdcfc21c8f 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -13,6 +13,8 @@ use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestArgumentResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributesArgumentResolver; /** * ControllerResolver. @@ -29,6 +31,11 @@ class ControllerResolver implements ControllerResolverInterface { private $logger; + /** + * @var ArgumentResolverManager + */ + private $argumentResolverManager; + /** * Constructor. * @@ -39,6 +46,14 @@ public function __construct(LoggerInterface $logger = null) $this->logger = $logger; } + /** + * @internal + */ + public function setArgumentResolverManager(ArgumentResolverManager $argumentResolverManager) + { + $this->argumentResolverManager = $argumentResolverManager; + } + /** * {@inheritdoc} * @@ -102,34 +117,20 @@ public function getArguments(Request $request, $controller) $r = new \ReflectionFunction($controller); } + $reflector = new \ReflectionMethod($this, 'doGetArguments'); + if ($reflector->getDeclaringClass()->getName() !== __CLASS__) { + @trigger_error('The ControllerResolverInterface::doGetArguments() method is deprecated since version 2.8 and will be removed in 3.0. Use the ArgumentResolverManager and custom ArgumentResolverInterface implementations instead.', E_USER_DEPRECATED); + } + return $this->doGetArguments($request, $controller, $r->getParameters()); } + /** + * @deprecated As of Symfony 2.8, to be removed in Symfony 3.0. Create a custom ArgumentResolverInterface implementation instead. + */ protected function doGetArguments(Request $request, $controller, array $parameters) { - $attributes = $request->attributes->all(); - $arguments = array(); - foreach ($parameters as $param) { - if (array_key_exists($param->name, $attributes)) { - $arguments[] = $attributes[$param->name]; - } elseif ($param->getClass() && $param->getClass()->isInstance($request)) { - $arguments[] = $request; - } elseif ($param->isDefaultValueAvailable()) { - $arguments[] = $param->getDefaultValue(); - } else { - if (is_array($controller)) { - $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); - } elseif (is_object($controller)) { - $repr = get_class($controller); - } else { - $repr = $controller; - } - - throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name)); - } - } - - return $arguments; + return $this->getArgumentResolverManager()->getArguments($request, $controller); } /** @@ -157,7 +158,7 @@ protected function createController($controller) } /** - * Returns an instantiated controller + * Returns an instantiated controller. * * @param string $class A class name * @@ -167,4 +168,16 @@ protected function instantiateController($class) { return new $class(); } + + private function getArgumentResolverManager() + { + if (null === $this->argumentResolverManager) { + $this->argumentResolverManager = new ArgumentResolverManager(array( + new RequestArgumentResolver(), + new RequestAttributesArgumentResolver(), + )); + } + + return $this->argumentResolverManager; + } } diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php index 6f805ed2dab77..4cf398b6ae3dd 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php @@ -57,6 +57,8 @@ public function getController(Request $request); * * @throws \RuntimeException When value for argument given is not provided * + * @deprecated As of Symfony 2.8, to be removed in Symfony 3.0. Use the ArgumentResolverManager instead. + * * @api */ public function getArguments(Request $request, $controller); diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php index c64c4c3939981..7b3d4b44479c9 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php @@ -13,6 +13,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; @@ -35,15 +36,16 @@ class ContainerAwareHttpKernel extends HttpKernel /** * Constructor. * - * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance - * @param ContainerInterface $container A ContainerInterface instance - * @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance - * @param RequestStack $requestStack A stack for master/sub requests - * @param bool $triggerDeprecation Whether or not to trigger the deprecation warning for the ContainerAwareHttpKernel + * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance + * @param ContainerInterface $container A ContainerInterface instance + * @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance + * @param RequestStack $requestStack A stack for master/sub requests + * @param ArgumentResolverManager $argumentResolverManager A manager to resolve arguments + * @param bool $triggerDeprecation Whether or not to trigger the deprecation warning for the ContainerAwareHttpKernel */ - public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null, $triggerDeprecation = true) + public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null, ArgumentResolverManager $argumentResolverManager = null, $triggerDeprecation = true) { - parent::__construct($dispatcher, $controllerResolver, $requestStack); + parent::__construct($dispatcher, $controllerResolver, $requestStack, $argumentResolverManager); if ($triggerDeprecation) { trigger_error('The '.__CLASS__.' class is deprecated since version 2.7 and will be removed in 3.0. Use the Symfony\Component\HttpKernel\HttpKernel class instead.', E_USER_DEPRECATED); diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php new file mode 100644 index 0000000000000..21c61f1829be9 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterArgumentResolversPass.php @@ -0,0 +1,45 @@ + + */ +class RegisterArgumentResolversPass implements CompilerPassInterface +{ + private $managerService; + private $resolverTag; + + public function __construct($managerService = 'argument_resolver.manager', $resolverTag = 'kernel.argument_resolver') + { + $this->managerService = $managerService; + $this->resolverTag = $resolverTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->managerService) && !$container->hasAlias($this->managerService)) { + return; + } + + $definition = $container->findDefinition($this->managerService); + $resolvers = array(); + + foreach ($container->findTaggedServiceIds($this->resolverTag) as $id => $tags) { + $priority = isset($tags[0]['priority']) ? $tags[0]['priority'] : 0; + $resolvers[$priority][] = new Reference($id); + } + + ksort($resolvers); + $resolvers = call_user_func_array('array_merge', $resolvers); + + $definition->replaceArgument(1, $resolvers); + } +} diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 473f780ca3cb6..d63259927305e 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -11,6 +11,9 @@ namespace Symfony\Component\HttpKernel; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestArgumentResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributesArgumentResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; @@ -42,17 +45,29 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface /** * Constructor. * - * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance - * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance - * @param RequestStack $requestStack A stack for master/sub requests + * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance + * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance + * @param RequestStack $requestStack A stack for master/sub requests + * @param ArgumentResolverManager $argumentResolverManager A manager to resolve the controller arguments * * @api */ - public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null) + public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverManager $argumentResolverManager = null) { $this->dispatcher = $dispatcher; $this->resolver = $resolver; $this->requestStack = $requestStack ?: new RequestStack(); + + if (null === $argumentResolverManager) { + $argumentResolverManager = new ArgumentResolverManager(array( + new RequestArgumentResolver(), + new RequestAttributesArgumentResolver(), + )); + } + + if (method_exists($resolver, 'setArgumentResolverManager')) { + $resolver->setArgumentResolverManager($argumentResolverManager); + } } /** @@ -141,6 +156,11 @@ private function handleRaw(Request $request, $type = self::MASTER_REQUEST) $controller = $event->getController(); // controller arguments + $reflector = new \ReflectionMethod($this->resolver, 'getArguments'); + if (0 !== strpos($reflector->getDeclaringClass()->getName(), 'Symfony\Component\HttpKernel\Controller\\')) { + @trigger_error('The ControllerResolverInterface::getArguments() method is deprecated since version 2.8 and will be removed in 3.0. Use the ArgumentResolverManager and custom ArgumentResolverInterface implementations instead.', E_USER_DEPRECATED); + } + $arguments = $this->resolver->getArguments($request, $controller); // call controller diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/PsrServerRequestArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/PsrServerRequestArgumentResolverTest.php new file mode 100644 index 0000000000000..49b53abe1aa57 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/PsrServerRequestArgumentResolverTest.php @@ -0,0 +1,67 @@ + + */ +class PsrServerRequestArgumentResolverTest extends \PHPUnit_Framework_TestCase +{ + private $httpMessageFactory; + private $resolver; + + protected function setUp() + { + $this->httpMessageFactory = $this->getMock('Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface', array('createRequest')); + $this->resolver = new PsrServerRequestArgumentResolver($this->httpMessageFactory); + } + + /** + * @dataProvider provideClasses + */ + public function testSupports($class, $supported = true) + { + $this->assertEquals($supported, $this->resolver->supports($this->getRequestMock(), $this->getReflectionParameterMock($class))); + } + + public function provideClasses() + { + return array( + array('Psr\Http\Message\ServerRequestInterface'), + array('Psr\Http\Message\RequestInterface'), + array('Psr\Http\Message\MessageInterface'), + array('\stdClass', false), + array('Symfony\Component\HttpFoundation\Request', false), + ); + } + + public function testResolvesUsingHttpMessageFactory() + { + $request = $this->getRequestMock(); + + $this->httpMessageFactory->expects($this->once())->method('createRequest')->with($request); + + $this->resolver->resolve($request, $this->getReflectionParameterMock()); + } + + private function getRequestMock() + { + return $this->getMock('Symfony\Component\HttpFoundation\Request'); + } + + private function getReflectionParameterMock($class = null) + { + $reflectionParameter = $this->getMockBuilder('ReflectionParameter')->disableOriginalConstructor()->getMock(); + + if (null !== $class) { + $reflectionClass = $this->getMockBuilder('ReflectionClass')->disableOriginalConstructor()->getMock(); + $reflectionClass->expects($this->any())->method('getName')->willReturn($class); + + $reflectionParameter->expects($this->any())->method('getClass')->will($this->returnValue($reflectionClass)); + } + + return $reflectionParameter; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestArgumentResolverTest.php new file mode 100644 index 0000000000000..ae6917829df91 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestArgumentResolverTest.php @@ -0,0 +1,63 @@ + + */ +class RequestArgumentResolverTest extends \PHPUnit_Framework_TestCase +{ + private $resolver; + + protected function setUp() + { + $this->resolver = new RequestArgumentResolver(); + } + + /** + * @dataProvider provideClasses + */ + public function testSupports($class, $supported = true) + { + $this->assertEquals($supported, $this->resolver->supports($this->getRequestMock(), $this->getReflectionParameterMock($class))); + } + + public function provideClasses() + { + return array( + array('Symfony\Component\HttpFoundation\Request'), + array('Symfony\Component\BrowerKit\Request', false), + array('\stdClass', false), + ); + } + + public function testResolvesToRequest() + { + $request = $this->getRequestMock(); + + $this->assertEquals($request, $this->resolver->resolve($request, $this->getReflectionParameterMock())); + } + + private function getRequestMock() + { + return $this->getMock('Symfony\Component\HttpFoundation\Request'); + } + + private function getReflectionParameterMock($class = null) + { + $reflectionParameter = $this->getMockBuilder('ReflectionParameter')->disableOriginalConstructor()->getMock(); + + if (null !== $class) { + $reflectionClass = $this->getMockBuilder('ReflectionClass')->disableOriginalConstructor()->getMock(); + $reflectionClass->expects($this->any())->method('isInstance')->will($this->returnCallback(function ($obj) use ($class) { + return is_a($obj, $class); + })); + + $reflectionParameter->expects($this->any())->method('getClass')->will($this->returnValue($reflectionClass)); + } + + return $reflectionParameter; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestAttributesArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestAttributesArgumentResolverTest.php new file mode 100644 index 0000000000000..55c3d38fb3d66 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolver/RequestAttributesArgumentResolverTest.php @@ -0,0 +1,60 @@ + + */ +class RequestAttributesArgumentResolverTest extends \PHPUnit_Framework_TestCase +{ + private $resolver; + + public function setUp() + { + $this->resolver = new RequestAttributesArgumentResolver(); + } + + /** + * @dataProvider provideParameters + */ + public function testSupports($parameterName, $supported = true) + { + $this->assertEquals($supported, $this->resolver->supports($this->getRequestMock(), $this->getReflectionParameterMock($parameterName))); + } + + public function provideParameters() + { + return array( + array('exists'), + array('not_exists', false), + ); + } + + public function testResolvesToRequestAttributeValues() + { + $this->assertEquals('value_of_exists', $this->resolver->resolve($this->getRequestMock(), $this->getReflectionParameterMock('exists'))); + } + + private function getRequestMock() + { + $request = $this->getMock('Symfony\Component\HttpFoundation\Request'); + $request->attributes = $this->getMock('Symfony\Component\HttpFoundation\ParameterBag'); + $request->attributes->expects($this->any())->method('has')->will($this->returnValueMap(array( + array('exists', true), + array('not_exists', false), + ))); + $request->attributes->expects($this->any())->method('get')->with('exists')->willReturn('value_of_exists'); + + return $request; + } + + private function getReflectionParameterMock($name) + { + $reflectionParameter = $this->getMockBuilder('ReflectionParameter')->disableOriginalConstructor()->getMock(); + $reflectionParameter->expects($this->any())->method('getName')->willReturn($name); + + return $reflectionParameter; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php new file mode 100644 index 0000000000000..e5e7087e73692 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverManagerTest.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Controller; + +use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager; + +class ArgumentResolverManagerTest extends \PHPUnit_Framework_TestCase +{ + private $manager; + private $resolver1; + private $resolver2; + private $request; + + public function setUp() + { + $this->resolver1 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolver\ArgumentResolverInterface'); + $this->resolver2 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolver\ArgumentResolverInterface'); + + $this->manager = new ArgumentResolverManager(array( + $this->resolver1, + $this->resolver2, + )); + + $this->request = $this->getMock('Symfony\Component\HttpFoundation\Request'); + } + + public function testGetArgumentsWithoutControllerParameters() + { + $this->assertArguments(array(), function () { }); + } + + public function testGetArgumentsFirstResolverAccepts() + { + $this->promiseResolverToMatch($this->resolver1, 'resolved_value'); + + $this->assertArguments(array('resolved_value'), $this->getControllerWithOneParameter()); + } + + public function testGetArgumentsSecondResolverAccepts() + { + $this->promiseResolverToNotMatch($this->resolver1); + $this->promiseResolverToMatch($this->resolver2, 'resolved_value'); + + $this->assertArguments(array('resolved_value'), $this->getControllerWithOneParameter()); + } + + /** + * @expectedException RuntimeException + */ + public function testGetArgumentsFailsIfNoResolverAccepts() + { + $this->promiseResolverToNotMatch($this->resolver1); + $this->promiseResolverToNotMatch($this->resolver2); + + $this->manager->getArguments($this->request, $this->getControllerWithOneParameter()); + } + + public function testGetArgumentResolvingMultipleParameters() + { + $this->resolver1->expects($this->any()) + ->method('supports') + ->will($this->onConsecutiveCalls(false, true, true)); + $this->resolver1->expects($this->any()) + ->method('resolve') + ->will($this->onConsecutiveCalls('1st resolved by 1', '2nd resolved by 1')); + + $this->resolver2->expects($this->any()) + ->method('supports') + ->will($this->onConsecutiveCalls(true, false, true)); + $this->resolver2->expects($this->any()) + ->method('resolve') + ->will($this->onConsecutiveCalls('1st resolved by 2', '2nd resolved by 2')); + + $this->assertArguments( + array('1st resolved by 2', '1st resolved by 1', '2nd resolved by 1'), + function ($a, $b, $c) { } + ); + } + + public function testControllerWithOneOptionalParameterWhichDoesNotMatch() + { + $this->promiseResolverToNotMatch($this->resolver1); + $this->promiseResolverToNotMatch($this->resolver2); + + $this->assertArguments(array('default'), function ($a = 'default') { }); + } + + public function testControllerWithOneOptionalParameterWhichDoesMatch() + { + $this->promiseResolverToMatch($this->resolver1, 'resolved by 1'); + $this->promiseResolverToNotMatch($this->resolver2); + + $this->assertArguments(array('resolved by 1'), function ($a = 'default') { }); + } + + public function testControllerWithOneParameterWithNullDefault() + { + $this->promiseResolverToNotMatch($this->resolver1); + $this->promiseResolverToNotMatch($this->resolver2); + + $this->assertArguments(array(null), function ($a = null) { }); + } + + private function assertArguments(array $expected, $controller) + { + $this->assertEquals($expected, $this->manager->getArguments($this->request, $controller)); + } + + private function promiseResolverToMatch($resolver, $return) + { + $resolver->expects($this->any())->method('supports')->will($this->returnValue(true)); + $resolver->expects($this->any())->method('resolve')->will($this->returnValue($return)); + } + + private function promiseResolverToNotMatch($resolver) + { + $resolver->expects($this->any())->method('supports')->will($this->returnValue(false)); + } + + private function getControllerWithOneParameter() + { + return function ($a) { }; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 32db4e47adc5a..ee5b7a8dc90e7 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -220,19 +220,19 @@ public function controllerMethod1($foo) { } - protected function controllerMethod2($foo, $bar = null) + public function controllerMethod2($foo, $bar = null) { } - protected function controllerMethod3($foo, $bar = null, $foobar) + public function controllerMethod3($foo, $bar = null, $foobar) { } - protected static function controllerMethod4() + public static function controllerMethod4() { } - protected function controllerMethod5(Request $request) + public function controllerMethod5(Request $request) { } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php index f64d7247c0b48..bcf7449de96ab 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php @@ -20,6 +20,11 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase { + /** + * Tagged as legacy because of the usage of the deprecated ControllerResolver#getArguments(). + * + * @group legacy + */ public function testStopwatchSections() { $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch = new Stopwatch()); @@ -39,6 +44,11 @@ public function testStopwatchSections() ), array_keys($events)); } + /** + * Tagged as legacy because of the usage of the deprecated ControllerResolver#getArguments(). + * + * @group legacy + */ public function testStopwatchCheckControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch') @@ -55,6 +65,11 @@ public function testStopwatchCheckControllerOnRequestEvent() $kernel->handle($request); } + /** + * Tagged as legacy because of the usage of the deprecated ControllerResolver#getArguments(). + * + * @group legacy + */ public function testStopwatchStopControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch') diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php index 4e487a478a600..bd2ef30a0da7d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php @@ -140,6 +140,11 @@ private function getKernelExpectingRequest(Request $request) return $kernel; } + /** + * Tagged as legacy because of the usage of the deprecated ControllerResolver#getArguments(). + * + * @group legacy + */ public function testExceptionInSubRequestsDoesNotMangleOutputBuffers() { $resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface'); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php index 5546ba2ed830e..a3b62b34272df 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestHttpKernel.php @@ -15,10 +15,11 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\Tests\TestArgumentResolverManager; +use Symfony\Component\HttpKernel\Tests\TestControllerResolver; -class TestHttpKernel extends HttpKernel implements ControllerResolverInterface +class TestHttpKernel extends HttpKernel { protected $body; protected $status; @@ -35,7 +36,7 @@ public function __construct($body, $status, $headers, \Closure $customizer = nul $this->headers = $headers; $this->customizer = $customizer; - parent::__construct(new EventDispatcher(), $this); + parent::__construct(new EventDispatcher(), new TestControllerResolver($this), null, new TestArgumentResolverManager()); } public function getBackendRequest() @@ -56,16 +57,6 @@ public function isCatchingExceptions() return $this->catch; } - public function getController(Request $request) - { - return array($this, 'callController'); - } - - public function getArguments(Request $request, $controller) - { - return array($request); - } - public function callController(Request $request) { $this->called = true; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php index 773e221482bed..19de6269aaae2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/TestMultipleHttpKernel.php @@ -15,10 +15,11 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\Tests\TestArgumentResolverManager; +use Symfony\Component\HttpKernel\Tests\TestControllerResolver; -class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface +class TestMultipleHttpKernel extends HttpKernel { protected $bodies = array(); protected $statuses = array(); @@ -34,7 +35,7 @@ public function __construct($responses) $this->headers[] = $response['headers']; } - parent::__construct(new EventDispatcher(), $this); + parent::__construct(new EventDispatcher(), new TestControllerResolver($this), null, new TestArgumentResolverManager()); } public function getBackendRequest() @@ -49,16 +50,6 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ return parent::handle($request, $type, $catch); } - public function getController(Request $request) - { - return array($this, 'callController'); - } - - public function getArguments(Request $request, $controller) - { - return array($request); - } - public function callController(Request $request) { $this->called = true; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 97e68f66f979a..573d670574dc2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -21,6 +21,11 @@ use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\EventDispatcher\EventDispatcher; +/** + * Tagged as legacy because of the usage of the deprecated ControllerResolver#getArguments(). + * + * @group legacy + */ class HttpKernelTest extends \PHPUnit_Framework_TestCase { /** diff --git a/src/Symfony/Component/HttpKernel/Tests/TestArgumentResolverManager.php b/src/Symfony/Component/HttpKernel/Tests/TestArgumentResolverManager.php new file mode 100644 index 0000000000000..093548cd5d979 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/TestArgumentResolverManager.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager; + +/** + * @author Wouter J + */ +class TestArgumentResolverManager extends ArgumentResolverManager +{ + public function getArguments(Request $request, $controller) + { + return array($request); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/TestControllerResolver.php b/src/Symfony/Component/HttpKernel/Tests/TestControllerResolver.php new file mode 100644 index 0000000000000..828b3ca36f2a7 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/TestControllerResolver.php @@ -0,0 +1,26 @@ + + */ +class TestControllerResolver extends ControllerResolver +{ + private $controller; + + public function __construct($controller, LoggerInterface $logger = null) + { + parent::__construct($logger); + $this->controller = $controller; + } + + public function getController(Request $request) + { + return array($this->controller, 'callController'); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php b/src/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php index d526c4de80c36..6330505102160 100644 --- a/src/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php +++ b/src/Symfony/Component/HttpKernel/Tests/TestHttpKernel.php @@ -14,24 +14,13 @@ use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\EventDispatcher\EventDispatcher; -class TestHttpKernel extends HttpKernel implements ControllerResolverInterface +class TestHttpKernel extends HttpKernel { public function __construct() { - parent::__construct(new EventDispatcher(), $this); - } - - public function getController(Request $request) - { - return array($this, 'callController'); - } - - public function getArguments(Request $request, $controller) - { - return array($request); + parent::__construct(new EventDispatcher(), new TestControllerResolver($this), null, new TestArgumentResolverManager()); } public function callController(Request $request) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy