8000 Merge pull request #3 from WouterJ/kernel-resolve-manager · wouterj/symfony@d72088c · GitHub
[go: up one dir, main page]

Skip to content

Commit d72088c

Browse files
committed
Merge pull request #3 from WouterJ/kernel-resolve-manager
[WIP] Created ArgumentResolverManager
2 parents cba4124 + 99a8b38 commit d72088c

File tree

3 files changed

+183
-2
lines changed

3 files changed

+183
-2
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\HttpKernel\Controller;
1313

14+
use Symfony\Component\HttpFoundation\Request;
15+
1416
/**
1517
* An ArgumentResolverInterface implementation resolves the arguments of
1618
* controllers.
@@ -23,18 +25,20 @@ interface ArgumentResolverInterface
2325
* Checks if the current parameter can be resolved by this argument
2426
* resolver.
2527
*
28+
* @param Request $request
2629
* @param \ReflectionParameter $parameter
2730
*
2831
* @return Boolean
2932
*/
30-
public function supports(\ReflectionParameter $parameter);
33+
public function accepts(Request $request, \ReflectionParameter $parameter);
3134

3235
/**
3336
* Resolves the current parameter into an argument.
3437
*
38+
* @param Request $request
3539
* @param \ReflectionParameter $parameter
3640
*
3741
* @return mixed The resolved argument
3842
*/
39-
public function resolve(\ReflectionParameter $parameter);
43+
public function resolve(Request $request, \ReflectionParameter $parameter);
4044
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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 resolver 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+
* Returns the arguments to pass to the controller.
31+
*
32+
* @param Request $request A Request instance
33+
* @param callable $controller A PHP callable
34+
*
35+
* @return array an array of arguments to pass to the controller
36+
*
37+
* @throws \RuntimeException When a parameter cannot be resolved
38+
*/
39+
public function getArguments(Request $request, $controller)
40+
{
41+
if (is_array($controller)) {
42+
$controllerReflection = new \ReflectionMethod($controller[0], $controller[1]);
43+
} elseif (is_object($controller) && !$controller instanceof \Closure) {
44+
$controllerReflection = new \ReflectionObject($controller);
45+
$controllerReflection = $r->getMethod('__invoke');
46+
} else {
47+
$controllerReflection = new \ReflectionFunction($controller);
48+
}
49+
50+
$parameters = $controllerReflection->getParameters();
51+
$arguments = array();
52+
53+
foreach ($parameters as $parameter) {
54+
foreach ($this->resolvers as $argumentResolver) {
55+
if ($argumentResolver->accepts($request, $parameter)) {
56+
$arguments[] = $argumentResolver->resolve($request, $parameter);
57+
continue 2;
58+
}
59+
}
60+
61+
if (is_array($controller)) {
62+
$repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
63+
} elseif (is_object($controller)) {
64+
$repr = get_class($controller);
65+
} else {
66+
$repr = $controller;
67+
}
68+
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, $parameter->name));
69+
}
70+
71+
return $arguments;
72+
}
73+
74+
public function addResolver(ArgumentResolverInterface $resolver)
75+
{
76+
$this->resolvers[] = $resolver;
77+
}
78+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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\Tests\Controller;
13+
14+
use Symfony\Component\HttpKernel\Controller\ArgumentResolverManager;
15+
16+
class ArgumentResolverManagerTest extends \PHPUnit_Framework_TestCase
17+
{
18+
protected $manager;
19+
protected $resolver1;
20+
protected $resolver2;
21+
protected $request;
22+
23+
public function setUp()
24+
{
25+
$this->manager = new ArgumentResolverManager();
26+
$this->resolver1 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
27+
$this->resolver2 = $this->getMock('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface');
28+
$this->manager->addResolver($this->resolver1);
29+
$this->manager->addResolver($this->resolver2);
30+
31+
$this->request = $this->getMock('Symfony\Component\HttpFoundation\Request');
32+
}
33+
34+
public function testGetArgumentsFirstResolverAccepts()
35+
{
36+
$this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(true));
37+
$this->resolver1->expects($this->any())
38+
->method('resolve')
39+
->will($this->returnValue('resolved_value'));
40+
41+
$controller = $this->getControllerWithOneArgument();
42+
43+
$arguments = $this->manager->getArguments($this->request, $controller);
44+
$this->assertEquals(array('resolved_value'), $arguments);
45+
}
46+
47+
public function testGetArgumentsSecondResolverAccepts()
48+
{
49+
$this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false));
50+
$this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(true));
51+
$this->resolver2->expects($this->any())
52+
->method('resolve')
53+
->will($this->returnValue('resolved_value'));
54+
55+
$controller = $this->getControllerWithOneArgument();
56+
57+
$arguments = $this->manager->getArguments($this->request, $controller);
58+
$this->assertEquals(array('resolved_value'), $arguments);
59+
}
60+
61+
/**
62+
* @expectedException RuntimeException
63+
*/
64+
public function testGetArgumentsFailsIfNoResolverAccepts()
65+
{
66+
$this->resolver1->expects($this->any())->method('accepts')->will($this->returnValue(false));
67+
$this->resolver2->expects($this->any())->method('accepts')->will($this->returnValue(false));
68+
69+
$controller = $this->getControllerWithOneArgument();
70+
$this->manager->getArguments($this->request, $controller);
71+
}
72+
73+
public function testGetArgumentResolvingMultipleArguments()
74+
{
75+
$this->resolver1->expects($this->any())
76+
->method('accepts')
77+
->will($this->onConsecutiveCalls(false, true, true));
78+
$this->resolver1->expects($this->any())
79+
->method('resolve')
80+
->will($this->onConsecutiveCalls('1st resolved by 1', '2nd resolved by 1'));
81+
82+
$this->resolver2->expects($this->any())
83+
->method('accepts')
84+
->will($this->onConsecutiveCalls(true, false, true));
85+
$this->resolver2->expects($this->any())
86+
->method('resolve')
87+
->will($this->onConsecutiveCalls('1st resolved by 2', '2nd resolved by 2'));
88+
89+
$controller = function ($a, $b, $c) { };
90+
91+
$arguments = $this->manager->getArguments($this->request, $controller);
92+
$this->assertEquals(array('1st resolved by 2< 5ABE /span>', '1st resolved by 1', '2nd resolved by 1'), $arguments);
93+
}
94+
95+
protected function getControllerWithOneArgument()
96+
{
97+
return function ($a) { };
98+
}
99+
}

0 commit comments

Comments
 (0)
0