Skip to content

Commit f7da1f0

Browse files
committed
added some unit tests (and fixed some bugs)
1 parent f17f586 commit f7da1f0

File tree

22 files changed

+697
-21
lines changed

22 files changed

+697
-21
lines changed

src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
1515
use Symfony\Bridge\Twig\Tests\TestCase;
16-
use Symfony\Component\HttpFoundation\Response;
1716
use Symfony\Component\HttpKernel\HttpContentRenderer;
1817

1918
class HttpKernelExtensionTest extends TestCase

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/HttpRenderingStrategyPass.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use Symfony\Component\DependencyInjection\Reference;
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
1616
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17-
use Symfony\Component\DependencyInjection\Exception\LogicException;
1817

1918
/**
2019
* Adds services tagged kernel.content_renderer_strategy as HTTP content rendering strategies.
@@ -31,6 +30,15 @@ public function process(ContainerBuilder $container)
3130

3231
$definition = $container->getDefinition('http_content_renderer');
3332
foreach (array_keys($container->findTaggedServiceIds('kernel.content_renderer_strategy')) as $id) {
33+
// We must assume that the class value has been correctly filled, even if the service is created by a factory
34+
$class = $container->getDefinition($id)->getClass();
35+
36+
$refClass = new \ReflectionClass($class);
37+
$interface = 'Symfony\Component\HttpKernel\RenderingStrategy\RenderingStrategyInterface';
38+
if (!$refClass->implementsInterface($interface)) {
39+
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
40+
}
41+
3442
$definition->addMethodCall('addStrategy', array(new Reference($id)));
3543
}
3644
}

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function build(ContainerBuilder $container)
6666
$container->addCompilerPass(new AddCacheClearerPass());
6767
$container->addCompilerPass(new TranslationExtractorPass());
6868
$container->addCompilerPass(new TranslationDumperPass());
69-
$container->addCompilerPass(new HttpRenderingStrategyPass());
69+
$container->addCompilerPass(new HttpRenderingStrategyPass(), PassConfig::TYPE_AFTER_REMOVING);
7070

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

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,12 @@
1919
<argument>%kernel.debug%</argument>
2020
</service>
2121

22-
<service id="http_content_renderer.strategy.default" class="%http_content_renderer.strategy.default.class%" public="false">
22+
<service id="http_content_renderer.strategy.default" class="%http_content_renderer.strategy.default.class%">
2323
<tag name="kernel.content_renderer_strategy" />
2424
<argument type="service" id="http_kernel" />
2525
<call method="setUrlGenerator"><argument type="service" id="router" /></call>
2626
</service>
2727

28-
<!-- FIXME: this service should be private but it cannot due to a bug in PhpDumper -->
2928
<service id="http_content_renderer.strategy.hinclude" class="%http_content_renderer.strategy.hinclude.class%">
3029
<tag name="kernel.content_renderer_strategy" />
3130
<argument type="service" id="templating" on-invalid="null" />

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<argument type="service" id="esi" on-invalid="ignore" />
1919
</service>
2020

21-
<service id="http_content_renderer.strategy.esi" class="%http_content_renderer.strategy.esi.class%" public="false">
21+
<service id="http_content_renderer.strategy.esi" class="%http_content_renderer.strategy.esi.class%">
2222
<tag name="kernel.content_renderer_strategy" />
2323
<argument type="service" id="esi" />
2424
<argument type="service" id="http_content_renderer.strategy.default" />
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
use Symfony\Component\DependencyInjection\Definition;
16+
use Symfony\Component\DependencyInjection\Reference;
17+
use Symfony\Component\HttpFoundation\Request;
18+
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\HttpRenderingStrategyPass;
19+
20+
class HttpRenderingStrategyPassTest extends \PHPUnit_Framework_TestCase
21+
{
22+
/**
23+
* Tests that content rendering not implementing RenderingStrategyInterface
24+
* trigger an exception.
25+
*
26+
* @expectedException \InvalidArgumentException
27+
*/
28+
public function testContentRendererWithoutInterface()
29+
{
30+
// one service, not implementing any interface
31+
$services = array(
32+
'my_content_renderer' => array(),
33+
);
34+
35+
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
36+
$definition->expects($this->atLeastOnce())
37+
->method('getClass')
38+
->will($this->returnValue('stdClass'));
39+
40+
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
41+
$builder->expects($this->any())
42+
->method('hasDefinition')
43+
->will($this->returnValue(true));
44+
45+
// We don't test kernel.content_renderer_strategy here
46+
$builder->expects($this->atLeastOnce())
47+
->method('findTaggedServiceIds')
48+
->will($this->returnValue($services));
49+
50+
$builder->expects($this->atLeastOnce())
51+
->method('getDefinition')
52+
->will($this->returnValue($definition));
53+
54+
$pass = new HttpRenderingStrategyPass();
55+
$pass->process($builder);
56+
}
57+
58+
public function testValidContentRenderer()
59+
{
60+
$services = array(
61+
'my_content_renderer' => array(),
62+
);
63+
64+
$renderer = $this->getMock('Symfony\Component\DependencyInjection\Definition');
65+
$renderer
66+
->expects($this->once())
67+
->method('addMethodCall')
68+
->with('addStrategy', array(new Reference('my_content_renderer')))
69+
;
70+
71+
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
72+
$definition->expects($this->atLeastOnce())
73+
->method('getClass')
74+
->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\RenderingStrategyService'));
75+
76+
$builder = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder');
77+
$builder->expects($this->any())
78+
->method('hasDefinition')
79+
->will($this->returnValue(true));
80+
81+
// We don't test kernel.content_renderer_strategy here
82+
$builder->expects($this->atLeastOnce())
83+
->method('findTaggedServiceIds')
84+
->will($this->returnValue($services));
85+
86+
$builder->expects($this->atLeastOnce())
87+
->method('getDefinition')
88+
->will($this->onConsecutiveCalls($renderer, $definition));
89+
90+
$pass = new HttpRenderingStrategyPass();
91+
$pass->process($builder);
92+
}
93+
}
94+
95+
class RenderingStrategyService implements \Symfony\Component\HttpKernel\RenderingStrategy\RenderingStrategyInterface
96+
{
97+
public function render($uri, Request $request = null, array $options = array())
98+
{
99+
}
100+
101+
public function getName()
102+
{
103+
return 'test';
104+
}
105+
}

src/Symfony/Component/Form/Tests/Extension/Validator/EventListener/ValidationListenerTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
use Symfony\Component\Form\FormInterface;
1515
use Symfony\Component\Form\FormBuilder;
16-
use Symfony\Component\Form\FormError;
1716
use Symfony\Component\Form\Util\PropertyPath;
1817
use Symfony\Component\Form\Extension\Validator\Constraints\Form;
1918
use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener;

src/Symfony/Component/HttpFoundation/Request.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,7 @@ public function getSchemeAndHttpHost()
926926
*/
927927
public function getUri()
928928
{
929-
$qs = $this->getQueryString();
930-
if (null !== $qs) {
929+
if (null !== $qs = $this->getQueryString()) {
931930
$qs = '?'.$qs;
932931
}
933932

src/Symfony/Component/HttpKernel/EventListener/RouterProxyListener.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public function onKernelRequest(GetResponseEvent $event)
5555

5656
parse_str($request->query->get('path', ''), $attributes);
5757
$request->attributes->add($attributes);
58-
$request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params'), $attributes));
58+
$request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', array()), $attributes));
5959
$request->query->remove('path');
6060
}
6161

@@ -76,7 +76,8 @@ protected function validateRequest(Request $request)
7676
}
7777

7878
// is the Request signed?
79-
if ($this->signer->check($request->getUri())) {
79+
// we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering)
80+
if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) {
8081
return;
8182
}
8283

src/Symfony/Component/HttpKernel/HttpContentRenderer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public function onKernelResponse(FilterResponseEvent $event)
9090
* @param array $options An array of options
9191
*
9292
* @return string|null The Response content or null when the Response is streamed
93+
*
94+
* @throws \InvalidArgumentException when the strategy does not exist
9395
*/
9496
public function render($uri, $strategy = 'default', array $options = array())
9597
{

src/Symfony/Component/HttpKernel/RenderingStrategy/DefaultRenderingStrategy.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public function __construct(HttpKernelInterface $kernel)
3636

3737
/**
3838
* {@inheritdoc}
39+
*
40+
* Additional available options:
41+
*
42+
* * alt: an alternative URI to render in case of an error
3943
*/
4044
public function render($uri, Request $request = null, array $options = array())
4145
{

src/Symfony/Component/HttpKernel/RenderingStrategy/EsiRenderingStrategy.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function __construct(Esi $esi, RenderingStrategyInterface $defaultStrateg
5656
*/
5757
public function render($uri, Request $request = null, array $options = array())
5858
{
59-
if (!$this->esi->hasSurrogateEsiCapability($request)) {
59+
if (null === $request || !$this->esi->hasSurrogateEsiCapability($request)) {
6060
return $this->defaultStrategy->render($uri, $request, $options);
6161
}
6262

@@ -69,7 +69,7 @@ public function render($uri, Request $request = null, array $options = array())
6969
$alt = $this->generateProxyUri($alt, $request);
7070
}
7171

72-
return $this->esi->renderIncludeTag($uri, $alt, $options['ignore_errors'], isset($options['comment']) ? $options['comment'] : '');
72+
return $this->esi->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');
7373
}
7474

7575
/**

src/Symfony/Component/HttpKernel/RenderingStrategy/GeneratorAwareRenderingStrategy.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public function setUrlGenerator(UrlGeneratorInterface $generator)
4646
* @param Request $request A Request instance
4747
*
4848
* @return string A proxy URI
49+
*
50+
* @throws \LogicException when the _proxy route is not available
51+
* @throws \LogicException when there is no registered route generator
4952
*/
5053
protected function generateProxyUri(ControllerReference $reference, Request $request = null)
5154
{
@@ -63,7 +66,7 @@ protected function generateProxyUri(ControllerReference $reference, Request $req
6366
}
6467

6568
try {
66-
$uri = $this->generator->generate('_proxy', array('_controller' => $reference->controller, '_format' => $format), true);
69+
$uri = $this->generator->generate('_proxy', array('_controller' => $reference->controller, '_format' => $format), UrlGeneratorInterface::ABSOLUTE_URL);
6770
} catch (RouteNotFoundException $e) {
6871
throw new \LogicException('Unable to generate a proxy URL as the "_proxy" route is not registered.', 0, $e);
6972
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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\EventListener;
13+
14+
use Symfony\Component\HttpKernel\EventListener\RouterProxyListener;
15+
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\HttpKernel\HttpKernelInterface;
17+
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
18+
use Symfony\Component\HttpKernel\UriSigner;
19+
20+
class RouterProxyListenerTest extends \PHPUnit_Framework_TestCase
21+
{
22+
protected function setUp()
23+
{
24+
if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
25+
$this->markTestSkipped('The "EventDispatcher" component is not available');
26+
}
27+
}
28+
29+
public function testOnlyTrigerredOnProxyRoute()
30+
{
31+
$request = Request::create('http://example.com/foo?path=foo%3D=bar');
32+
33+
$listener = new RouterProxyListener(new UriSigner('foo'));
34+
$event = $this->createGetResponseEvent($request, 'foobar');
35+
36+
$expected = $request->attributes->all();
37+
38+
$listener->onKernelRequest($event);
39+
40+
$this->assertEquals($expected, $request->attributes->all());
41+
$this->assertTrue($request->query->has('path'));
42+
}
43+
44+
/**
45+
* @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
46+
*/
47+
public function testAccessDeniedWithNonSafeMethods()
48+
{
49+
$request = Request::create('http://example.com/foo', 'POST');
50+
51+
$listener = new RouterProxyListener(new UriSigner('foo'));
52+
$event = $this->createGetResponseEvent($request);
53+
54+
$listener->onKernelRequest($event);
55+
}
56+
57+
/**
58+
* @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
59+
*/
60+
public function testAccessDeniedWithNonLocalIps()
61+
{
62+
$request = Request::create('http://example.com/foo', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
63+
64+
$listener = new RouterProxyListener(new UriSigner('foo'));
65+
$event = $this->createGetResponseEvent($request);
66+
67+
$listener->onKernelRequest($event);
68+
}
69+
70+
/**
71+
* @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
72+
*/
73+
public function testAccessDeniedWithWrongSignature()
74+
{
75+
$request = Request::create('http://example.com/foo', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
76+
77+
$listener = new RouterProxyListener(new UriSigner('foo'));
78+
$event = $this->createGetResponseEvent($request);
79+
80+
$listener->onKernelRequest($event);
81+
}
82+
83+
public function testWithSignatureAndNoPath()
84+
{
85+
$signer = new UriSigner('foo');
86+
$request = Request::create($signer->sign('http://example.com/foo'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
87+
88+
$listener = new RouterProxyListener($signer);
89+
$event = $this->createGetResponseEvent($request);
90+
91+
$listener->onKernelRequest($event);
92+
93+
$this->assertEquals(array('foo' => 'foo'), $request->attributes->get('_route_params'));
94+
$this->assertFalse($request->query->has('path'));
95+
}
96+
97+
public function testWithSignatureAndPath()
98+
{
99+
$signer = new UriSigner('foo');
100+
$request = Request::create($signer->sign('http://example.com/foo?path=bar%3Dbar'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1'));
101+
102+
$listener = new RouterProxyListener($signer);
103+
$event = $this->createGetResponseEvent($request);
104+
105+
$listener->onKernelRequest($event);
106+
107+
$this->assertEquals(array('foo' => 'foo', 'bar' => 'bar'), $request->attributes->get('_route_params'));
108+
$this->assertFalse($request->query->has('path'));
109+
}
110+
111+
private function createGetResponseEvent(Request $request, $route = '_proxy')
112+
{
113+
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
114+
$request->attributes->set('_route', $route);
115+
$request->attributes->set('_route_params', array('foo' => 'foo'));
116+
117+
return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
118+
}
119+
}

0 commit comments

Comments
 (0)