Skip to content

Commit 7a8cfae

Browse files
committed
Refactored argument resolving out of the ControllerResolver
1 parent 7baeaa2 commit 7a8cfae

16 files changed

+464
-21
lines changed

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
3434
use Symfony\Component\HttpFoundation\Request;
3535
use Symfony\Component\HttpKernel\Bundle\Bundle;
36+
use Symfony\Component\HttpKernel\DependencyInjection\RegisterArgumentResolversPass;
3637

3738
/**
3839
* Bundle.
@@ -81,6 +82,7 @@ public function build(ContainerBuilder $container)
8182
$container->addCompilerPass(new TranslationDumperPass());
8283
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
8384
$container->addCompilerPass(new SerializerPass());
85+
$container->addCompilerPass(new RegisterArgumentResolversPass());
8486

8587
if ($container->getParameter('kernel.debug')) {
8688
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);

src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<argument type="service" id="service_container" />
2626
<argument type="service" id="controller_resolver" />
2727
<argument type="service" id="request_stack" />
28+
<argument type="service" id="argument_resolver.manager" />
2829
</service>
2930

3031
<service id="request_stack" class="%request_stack.class%" />

src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
<parameters>
88
<parameter key="controller_resolver.class">Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver</parameter>
9+
<parameter key="argument_resolver.manager.class">Symfony\Component\HttpKernel\Controller\ArgumentResolverManager</parameter>
10+
<parameter key="argument_resolver.request.class">Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestArgumentResolver</parameter>
11+
<parameter key="argument_resolver.request_attributes.class">Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributesArgumentResolver</parameter>
912
<parameter key="controller_name_converter.class">Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser</parameter>
1013
<parameter key="response_listener.class">Symfony\Component\HttpKernel\EventListener\ResponseListener</parameter>
1114
<parameter key="streamed_response_listener.class">Symfony\Component\HttpKernel\EventListener\StreamedResponseListener</parameter>
@@ -25,6 +28,16 @@
2528
<argument type="service" id="logger" on-invalid="ignore" />
2629
</service>
2730

31+
<service id="argument_resolver.manager" class="%argument_resolver.manager.class%" />
32+
33+
<service id="argument_resolver.request" class="%argument_resolver.request.class%">
34+
<tag name="kernel.argument_resolver" />
35+
</service>
36+
37+
<service id="argument_resolver.request_attributes" class="%argument_resolver.request_attributes.class%">
38+
<tag name="kernel.argument_resolver" />
39+
</service>
40+
2841
<service id="response_listener" class="%response_listener.class%">
2942
<tag name="kernel.event_subscriber" />
3043
<argument>%kernel.charset%</argument>

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
CHANGELOG
22
=========
33

4+
* added argument resolvers
5+
* deprecated `Symfony\Component\HttpKernel\Controller\ControllerResolver#getArguments()` and `doGetArguments()`, use argument resolvers instead
6+
47
2.5.0
58
-----
69

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\Controller\ArgumentResolver;
13+
14+
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
15+
use Symfony\Component\HttpFoundation\Request;
16+
17+
/**
18+
* Resolves arguments typehinting for the Request object.
19+
*
20+
* @author Wouter J <wouter@wouterj.nl>
21+
*/
22+
class RequestArgumentResolver implements ArgumentResolverInterface
23+
{
24+
/**
25+
* {@inheritDoc}
26+
*/
27+
public function accepts(Request $request, \ReflectionParameter $parameter)
28+
{
29+
$class = $parameter->getClass();
30+
31+
return $class && $class->isInstance($request);
32+
}
33+
34+
/**
35+
* {@inheritDoc}
36+
*/
37+
public function resolve(Request $request, \ReflectionParameter $parameter)
38+
{
39+
return $request;
40+
}
41+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\Controller\ArgumentResolver;
13+
14+
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
15+
use Symfony\Component\HttpFoundation\Request;
16+
17+
/**
18+
* Resolves arguments which names are equal to the name of a request attribute.
19+
*
20+
* @author Wouter J <wouter@wouterj.nl>
21+
*/
22+
class RequestAttributesArgumentResolver implements ArgumentResolverInterface
23+
{
24+
/**
25+
* {@inheritDoc}
26+
*/
27+
public function accepts(Request $request, \ReflectionParameter $parameter)
28+
{
29+
return array_key_exists($parameter->name, $request->attributes->all());
30+
}
31+
32+
/**
33+
* {@inheritDoc}
34+
*/
35+
public function resolve(Request $request, \ReflectionParameter $parameter)
36+
{
37+
$attributes = $request->attributes->all();
38+
39+
return $attributes[$parameter->name];
40+
}
41+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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\Controller;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
16+
/**
17+
* An ArgumentResolverInterface implementation resolves the arguments of
18+
* controllers.
19+
*
20+
* @author Wouter J <wouter@wouterj.nl>
21+
*/
22+
interface ArgumentResolverInterface
23+
{
24+
/**
25+
* Checks if the current parameter can be resolved by this argument
26+
* resolver.
27+
*
28+
* @param Request $request
29+
* @param \ReflectionParameter $parameter
30+
*
31+
* @return Boolean
32+
*/
33+
public function accepts(Request $request, \ReflectionParameter $parameter);
34+
35+
/**
36+
* Resolves the current parameter into an argument.
37+
*
38+
* @param Request $request
39+
* @param \ReflectionParameter $parameter
40+
*
41+
* @return mixed The resolved argument
42+
*/
43+
public function resolve(Request $request, \ReflectionParameter $parameter);
44+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
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\Controller;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
16+
/**
17+
* The ArgumentResolverManager chains over the registered argument resolvers to
18+
* resolve all controller arguments.
19+
*
20+
* @author Wouter J <wouter@wouterj.nl>
21+
*/
22+
class ArgumentResolverManager
23+
{
24+
/**
25+
* @var ArgumentResolverInterface[]
26+
*/
27+
protected $resolvers = array();
28+
29+
/**
30+
* Adds an argument resolver.
31+
*
32+
* @param ArgumentResolverInterface $resolver
33+
*/
34+
public function addResolver(ArgumentResolverInterface $resolver)
35+
{
36+
$this->resolvers[] = $resolver;
37+
}
38+
39+
/**
40+
* Returns the arguments to pass to the controller.
41+
*
42+
* @param Request $request A Request instance
43+
* @param callable $controller A PHP callable
44+
*
45+
* @return array an array of arguments to pass to the controller
46+
*
47+
* @throws \RuntimeException When a parameter cannot be resolved
48+
*/
49+
public function getArguments(Request $request, $controller)
50+
{
51+
if (is_array($controller)) {
52+
$controllerReflection = new \ReflectionMethod($controller[0], $controller[1]);
53+
} elseif (is_object($controller) && !$controller instanceof \Closure) {
54+
$controllerReflection = new \ReflectionObject($controller);
55+
$controllerReflection = $controllerReflection->getMethod('__invoke');
56+
} else {
57+
$controllerReflection = new \ReflectionFunction($controller);
58+
}
59+
60+
$parameters = $controllerReflection->getParameters();
61+
$arguments = array();
62+
63+
foreach ($parameters as $parameter) {
64+
foreach ($this->resolvers as $argumentResolver) {
65+
if ($argumentResolver->accepts($request, $parameter)) {
66+
$arguments[] = $argumentResolver->resolve($request, $parameter);
67+
continue 2;
68+
}
69+
}
70+
71+
if ($parameter->isDefaultValueAvailable()) {
72+
$arguments[] = $parameter->getDefaultValue();
73+
} else {
74+
if (is_array($controller)) {
75+
$repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
76+
} elseif (is_object($controller)) {
77+
$repr = get_class($controller);
78+
} else {
79+
$repr = $controller;
80+
}
81+
82+
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));
83+
}
84+
}
85+
86+
return $arguments;
87+
}
88+
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ public function getController(Request $request)
8282
* {@inheritdoc}
8383
*
8484
* @api
85+
*
86+
* @deprecated Deprecated since Symfony 2.6, will be removed in Symfony 3.0. Use ArgumentResolvers instead
8587
*/
8688
public function getArguments(Request $request, $controller)
8789
{
@@ -97,6 +99,9 @@ public function getArguments(Request $request, $controller)
9799
return $this->doGetArguments($request, $controller, $r->getParameters());
98100
}
99101

102+
/**
103+
* @deprecated Deprecated since Symfony 2.6, will be removed in Symfony 3.0. Use ArgumentResolvers instead
104+
*/
100105
protected function doGetArguments(Request $request, $controller, array $parameters)
101106
{
102107
$attributes = $request->attributes->all();

src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\HttpFoundation\RequestStack;
1616
use Symfony\Component\HttpKernel\HttpKernelInterface;
1717
use Symfony\Component\HttpKernel\HttpKernel;
18+
use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager;
1819
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
1920
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
2021
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -37,10 +38,11 @@ class ContainerAwareHttpKernel extends HttpKernel
3738
* @param ContainerInterface $container A ContainerInterface instance
3839
* @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance
3940
* @param RequestStack $requestStack A stack for master/sub requests
41+
* @param ArgumentResolverManager $argumentResolver An ArgumentResolverManager instance
4042
*/
41-
public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null)
43+
public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver, RequestStack $requestStack = null, ArgumentResolverManager $argumentResolver = null)
4244
{
43-
parent::__construct($dispatcher, $controllerResolver, $requestStack);
45+
parent::__construct($dispatcher, $controllerResolver, $requestStack, $argumentResolver);
4446

4547
$this->container = $container;
4648

0 commit comments

Comments
 (0)
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