Skip to content

Commit 360fc5f

Browse files
author
Iltar van der Berg
committed
Extracting arg resolving from ControllerResolver
1 parent 8e1c60a commit 360fc5f

18 files changed

+373
-61
lines changed

UPGRADE-3.1.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ HttpKernel
6565
* Passing objects as URI attributes to the ESI and SSI renderers has been
6666
deprecated and will be removed in Symfony 4.0. The inline fragment
6767
renderer should be used with object attributes.
68+
* The `ControllerResolver::getArguments()` method is deprecated and will be
69+
removed in 4.0. If you have your own `ControllerResolverInterface`
70+
implementation, you should replace this method by implementing the
71+
`ArgumentResolverInterface` and injecting it in the HttpKernel.
6872

6973
Serializer
7074
----------

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,6 @@ public function load(array $configs, ContainerBuilder $container)
150150

151151
$loader->load('debug.xml');
152152

153-
$definition = $container->findDefinition('http_kernel');
154-
$definition->replaceArgument(1, new Reference('debug.controller_resolver'));
155-
156153
// replace the regular event_dispatcher service with the debug one
157154
$definition = $container->findDefinition('event_dispatcher');
158155
$definition->setPublic(false);
@@ -173,6 +170,7 @@ public function load(array $configs, ContainerBuilder $container)
173170
'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener',
174171
'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener',
175172
'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver',
173+
'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver',
176174
'Symfony\\Component\\HttpKernel\\Event\\KernelEvent',
177175
'Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent',
178176
'Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent',

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,14 @@
1717
<argument type="service" id="logger" on-invalid="null" />
1818
</service>
1919

20-
<service id="debug.controller_resolver" class="Symfony\Component\HttpKernel\Controller\TraceableControllerResolver">
21-
<argument type="service" id="controller_resolver" />
20+
<service id="debug.controller_resolver" decorates="controller_resolver" class="Symfony\Component\HttpKernel\Controller\TraceableControllerResolver">
21+
<argument type="service" id="debug.controller_resolver.inner" />
22+
<argument type="service" id="debug.stopwatch" />
23+
<argument type="service" id="argument_resolver" />
24+
</service>
25+
26+
<service id="debug.argument_resolver" decorates="argument_resolver" class="Symfony\Component\HttpKernel\Controller\TraceableArgumentResolver">
27+
<argument type="service" id="debug.argument_resolver.inner" />
2228
<argument type="service" id="debug.stopwatch" />
2329
</service>
2430
</services>

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<argument type="service" id="event_dispatcher" />
1414
<argument type="service" id="controller_resolver" />
1515
<argument type="service" id="request_stack" />
16+
<argument type="service" id="argument_resolver" />
1617
</service>
1718

1819
<service id="request_stack" class="Symfony\Component\HttpFoundation\RequestStack" />

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
<argument type="service" id="logger" on-invalid="ignore" />
1818
</service>
1919

20+
<service id="argument_resolver" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver" public="false" />
21+
2022
<service id="response_listener" class="Symfony\Component\HttpKernel\EventListener\ResponseListener">
2123
<tag name="kernel.event_subscriber" />
2224
<argument>%kernel.charset%</argument>

src/Symfony/Bundle/FrameworkBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"symfony/config": "~2.8|~3.0",
2424
"symfony/event-dispatcher": "~2.8|~3.0",
2525
"symfony/http-foundation": "~3.1",
26-
"symfony/http-kernel": "~2.8|~3.0",
26+
"symfony/http-kernel": "~3.1",
2727
"symfony/polyfill-mbstring": "~1.0",
2828
"symfony/filesystem": "~2.8|~3.0",
2929
"symfony/finder": "~2.8|~3.0",

src/Symfony/Component/HttpKernel/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ CHANGELOG
44
3.1.0
55
-----
66
* deprecated passing objects as URI attributes to the ESI and SSI renderers
7+
* Added an `ArgumentResolver` with `getArguments()` and the respective interface `ArgumentResolverInterface`
8+
* Deprecated `ControllerResolver::getArguments()`, which uses the `ArgumentResolver` as BC layer by extending it
9+
* The `HttpKernel` now accepts an additional argument for an `ArgumentResolver`
710

811
3.0.0
912
-----
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
* Responsible for the creation of the action arguments.
18+
*
19+
* @author Fabien Potencier <[email protected]>
20+
*/
21+
class ArgumentResolver implements ArgumentResolverInterface
22+
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
public function getArguments(Request $request, $controller)
27+
{
28+
if (is_array($controller)) {
29+
$r = new \ReflectionMethod($controller[0], $controller[1]);
30+
} elseif (is_object($controller) && !$controller instanceof \Closure) {
31+
$r = new \ReflectionObject($controller);
32+
$r = $r->getMethod('__invoke');
33+
} else {
34+
$r = new \ReflectionFunction($controller);
35+
}
36+
37+
return $this->doGetArguments($request, $controller, $r->getParameters());
38+
}
39+
40+
protected function doGetArguments(Request $request, $controller, array $parameters)
41+
{
42+
$attributes = $request->attributes->all();
43+
$arguments = array();
44+
foreach ($parameters as $param) {
45+
if (array_key_exists($param->name, $attributes)) {
46+
if (PHP_VERSION_ID >= 50600 && $param->isVariadic() && is_array($attributes[$param->name])) {
47+
$arguments = array_merge($arguments, array_values($attributes[$param->name]));
48+
} else {
49+
$arguments[] = $attributes[$param->name];
50+
}
51+
} elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
52+
$arguments[] = $request;
53+
} elseif ($param->isDefaultValueAvailable()) {
54+
$arguments[] = $param->getDefaultValue();
55+
} else {
56+
if (is_array($controller)) {
57+
$repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
58+
} elseif (is_object($controller)) {
59+
$repr = get_class($controller);
60+
} else {
61+
$repr = $controller;
62+
}
63+
64+
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));
65+
}
66+
}
67+
68+
return $arguments;
69+
}
70+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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 knows how to determine the
18+
* arguments for a specific action.
19+
*
20+
* @author Fabien Potencier <[email protected]>
21+
*/
22+
interface ArgumentResolverInterface
23+
{
24+
/**
25+
* Returns the arguments to pass to the controller.
26+
*
27+
* @param Request $request A Request instance
28+
* @param callable $controller A PHP callable
29+
*
30+
* @return array An array of arguments to pass to the controller
31+
*
32+
* @throws \RuntimeException When value for argument given is not provided
33+
*/
34+
public function getArguments(Request $request, $controller);
35+
}

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

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*
2424
* @author Fabien Potencier <[email protected]>
2525
*/
26-
class ControllerResolver implements ControllerResolverInterface
26+
class ControllerResolver extends ArgumentResolver implements ControllerResolverInterface
2727
{
2828
private $logger;
2929

@@ -84,50 +84,24 @@ public function getController(Request $request)
8484

8585
/**
8686
* {@inheritdoc}
87+
*
88+
* @deprecated this method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface or extend the ArgumentResolver instead.
8789
*/
8890
public function getArguments(Request $request, $controller)
8991
{
90-
if (is_array($controller)) {
91-
$r = new \ReflectionMethod($controller[0], $controller[1]);
92-
} elseif (is_object($controller) && !$controller instanceof \Closure) {
93-
$r = new \ReflectionObject($controller);
94-
$r = $r->getMethod('__invoke');
95-
} else {
96-
$r = new \ReflectionFunction($controller);
97-
}
92+
@trigger_error(sprintf('%s is deprecated as of 3.1 and will be removed in 4.0. Implement the %s or extend the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class, ArgumentResolver::class), E_USER_DEPRECATED);
9893

99-
return $this->doGetArguments($request, $controller, $r->getParameters());
94+
return parent::getArguments($request, $controller);
10095
}
10196

97+
/**
98+
* @deprecated this method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface or extend the ArgumentResolver instead.
99+
*/
102100
protected function doGetArguments(Request $request, $controller, array $parameters)
103101
{
104-
$attributes = $request->attributes->all();
105-
$arguments = array();
106-
foreach ($parameters as $param) {
107-
if (array_key_exists($param->name, $attributes)) {
108-
if (PHP_VERSION_ID >= 50600 && $param->isVariadic() && is_array($attributes[$param->name])) {
109-
$arguments = array_merge($arguments, array_values($attributes[$param->name]));
110-
} else {
111-
$arguments[] = $attributes[$param->name];
112-
}
113-
} elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
114-
$arguments[] = $request;
115-
} elseif ($param->isDefaultValueAvailable()) {
116-
$arguments[] = $param->getDefaultValue();
117-
} else {
118-
if (is_array($controller)) {
119-
$repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
120-
} elseif (is_object($controller)) {
121-
$repr = get_class($controller);
122-
} else {
123-
$repr = $controller;
124-
}
125-
126-
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));
127-
}
128-
}
102+
@trigger_error(sprintf('%s is deprecated as of 3.1 and will be removed in 4.0. Implement the %s or extend the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class, ArgumentResolver::class), E_USER_DEPRECATED);
129103

130-
return $arguments;
104+
return parent::doGetArguments($request, $controller, $parameters);
131105
}
132106

133107
/**

0 commit comments

Comments
 (0)