Skip to content

Commit 43e32b8

Browse files
committed
feature #21164 [HttpKernel] Added the SessionValueResolver (iltar)
This PR was merged into the 3.3-dev branch. Discussion ---------- [HttpKernel] Added the SessionValueResolver | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #21159 | License | MIT | Doc PR | (soon) This feature adds the `SessionValueResolver`. That means that you no longer have to rely on injecting a `SessionInterface` implementation via the constructor or getting this implementation from the `Request`. Regardless of method, it does not know about the `getFlashBag()`. By adding the `Session` to the action arguments, you can now type-hint against the implementation rather than interface, which contains the `getFlashBag()`, making it accessible rather than using duck-typing. _It should also feel less like injecting a service into the constructor which has a state or getting a service from the request._ **Old Situation** ```php class Controller { public function __construct(SessionInterface $session) { /* ... */ } public function fooAction(Request $request) { $this->get('session')->get(...); $request->getSession()->get(...); $this->session->get(...) // duck-typing $this->get('session')->getFlashBag(); $request->getSession()->getFlashBag(); $this->session->getFlashBag(); $this->addFlash(...); } } ``` **New Situation** _- The controller shortcut for flashbag could in theory be removed now_ ```php class Controller { public function fooAction(Session $session) { $session->get(...); $session->getFlashBag(); } } ``` Commits ------- b4464dc Added the SessionValueResolver
2 parents e58be70 + b4464dc commit 43e32b8

File tree

5 files changed

+161
-10
lines changed

5 files changed

+161
-10
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
<tag name="controller.argument_value_resolver" priority="50" />
3333
</service>
3434

35+
<service id="argument_resolver.session" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver" public="false">
36+
<tag name="controller.argument_value_resolver" priority="50" />
37+
</service>
38+
3539
<service id="argument_resolver.default" class="Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver" public="false">
3640
<tag name="controller.argument_value_resolver" priority="-100" />
3741
</service>

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

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
1616
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
1717
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
18+
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
1819
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
1920
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
2021
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
@@ -85,6 +86,7 @@ public static function getDefaultArgumentValueResolvers()
8586
return array(
8687
new RequestAttributeValueResolver(),
8788
new RequestValueResolver(),
89+
new SessionValueResolver(),
8890
new DefaultValueResolver(),
8991
new VariadicValueResolver(),
9092
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
16+
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
17+
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
18+
19+
/**
20+
* Yields the Session.
21+
*
22+
* @author Iltar van der Berg <kjarli@gmail.com>
23+
*/
24+
final class SessionValueResolver implements ArgumentValueResolverInterface
25+
{
26+
/**
27+
* {@inheritdoc}
28+
*/
29+
public function supports(Request $request, ArgumentMetadata $argument)
30+
{
31+
if (SessionInterface::class !== $argument->getType() && !is_subclass_of($argument->getType(), SessionInterface::class)) {
32+
return false;
33+
}
34+
35+
$session = $request->getSession();
36+
37+
if (null === $session) {
38+
return false;
39+
}
40+
41+
$class = get_class($session);
42+
43+
return $class === $argument->getType() || is_subclass_of($class, $argument->getType());
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function resolve(Request $request, ArgumentMetadata $argument)
50+
{
51+
yield $request->getSession();
52+
}
53+
}

src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php

+84-10
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
namespace Symfony\Component\HttpKernel\Tests\Controller;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpFoundation\Session\Session;
16+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
17+
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
1518
use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
16-
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
1719
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
18-
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
19-
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
2020
use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
2121
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
2222
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest;
23+
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingSession;
2324
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController;
2425
use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController;
2526
use Symfony\Component\HttpFoundation\Request;
@@ -32,14 +33,8 @@ class ArgumentResolverTest extends TestCase
3233
public static function setUpBeforeClass()
3334
{
3435
$factory = new ArgumentMetadataFactory();
35-
$argumentValueResolvers = array(
36-
new RequestAttributeValueResolver(),
37-
new RequestValueResolver(),
38-
new DefaultValueResolver(),
39-
new VariadicValueResolver(),
40-
);
4136

42-
self::$resolver = new ArgumentResolver($factory, $argumentValueResolvers);
37+
self::$resolver = new ArgumentResolver($factory);
4338
}
4439

4540
public function testDefaultState()
@@ -241,6 +236,73 @@ public function testGetNullableArgumentsWithDefaults()
241236
$this->assertEquals(array(null, null, 'value', 'mandatory'), self::$resolver->getArguments($request, $controller));
242237
}
243238

239+
public function testGetSessionArguments()
240+
{
241+
$session = new Session(new MockArraySessionStorage());
242+
$request = Request::create('/');
243+
$request->setSession($session);
244+
$controller = array($this, 'controllerWithSession');
245+
246+
$this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
247+
}
248+
249+
public function testGetSessionArgumentsWithExtendedSession()
250+
{
251+
$session = new ExtendingSession(new MockArraySessionStorage());
252+
$request = Request::create('/');
253+
$request->setSession($session);
254+
$controller = array($this, 'controllerWithExtendingSession');
255+
256+
$this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
257+
}
258+
259+
public function testGetSessionArgumentsWithInterface()
260+
{
261+
$session = $this->getMockBuilder(SessionInterface::class)->getMock();
262+
$request = Request::create('/');
263+
$request->setSession($session);
264+
$controller = array($this, 'controllerWithSessionInterface');
265+
266+
$this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
267+
}
268+
269+
/**
270+
* @expectedException \RuntimeException
271+
*/
272+
public function testGetSessionMissMatchWithInterface()
273+
{
274+
$session = $this->getMockBuilder(SessionInterface::class)->getMock();
275+
$request = Request::create('/');
276+
$request->setSession($session);
277+
$controller = array($this, 'controllerWithExtendingSession');
278+
279+
self::$resolver->getArguments($request, $controller);
280+
}
281+
282+
/**
283+
* @expectedException \RuntimeException
284+
*/
285+
public function testGetSessionMissMatchWithImplementation()
286+
{
287+
$session = new Session(new MockArraySessionStorage());
288+
$request = Request::create('/');
289+
$request->setSession($session);
290+
$controller = array($this, 'controllerWithExtendingSession');
291+
292+
self::$resolver->getArguments($request, $controller);
293+
}
294+
295+
/**
296+
* @expectedException \RuntimeException
297+
*/
298+
public function testGetSessionMissMatchOnNull()
299+
{
300+
$request = Request::create('/');
301+
$controller = array($this, 'controllerWithExtendingSession');
302+
303+
self::$resolver->getArguments($request, $controller);
304+
}
305+
244306
public function __invoke($foo, $bar = null)
245307
{
246308
}
@@ -268,6 +330,18 @@ protected function controllerWithRequest(Request $request)
268330
protected function controllerWithExtendingRequest(ExtendingRequest $request)
269331
{
270332
}
333+
334+
protected function controllerWithSession(Session $session)
335+
{
336+
}
337+
338+
protected function controllerWithSessionInterface(SessionInterface $session)
339+
{
340+
}
341+
342+
protected function controllerWithExtendingSession(ExtendingSession $session)
343+
{
344+
}
271345
}
272346

273347
function controller_function($foo, $foobar)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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\Fixtures\Controller;
13+
14+
use Symfony\Component\HttpFoundation\Session\Session;
15+
16+
class ExtendingSession extends Session
17+
{
18+
}

0 commit comments

Comments
 (0)