diff --git a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
index 98b98f1983..69d6d326f4 100644
--- a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
@@ -12,6 +12,8 @@
namespace Symfony\Bridge\Twig\Extension;
use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\RequestContext;
/**
* Twig extension for the Symfony HttpFoundation component.
@@ -21,10 +23,12 @@ use Symfony\Component\HttpFoundation\RequestStack;
class HttpFoundationExtension extends \Twig_Extension
{
private $requestStack;
+ private $requestContext;
- public function __construct(RequestStack $requestStack)
+ public function __construct(RequestStack $requestStack, RequestContext $requestContext = null)
{
$this->requestStack = $requestStack;
+ $this->requestContext = $requestContext;
}
/**
@@ -56,6 +60,23 @@ class HttpFoundationExtension extends \Twig_Extension
}
if (!$request = $this->requestStack->getMasterRequest()) {
+ if (null !== $this->requestContext && '' !== $host = $this->requestContext->getHost()) {
+ $scheme = $this->requestContext->getScheme();
+ $port = '';
+
+ if ('http' === $scheme && 80 != $this->requestContext->getHttpPort()) {
+ $port = ':'.$this->requestContext->getHttpPort();
+ } elseif ('https' === $scheme && 443 != $this->requestContext->getHttpsPort()) {
+ $port = ':'.$this->requestContext->getHttpsPort();
+ }
+
+ if ('/' !== $path[0]) {
+ $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path;
+ }
+
+ return $scheme.'://'.$host.$port.$path;
+ }
+
return $path;
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
index 91f978a909..339d43d7c6 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
@@ -14,6 +14,7 @@ namespace Symfony\Bridge\Twig\Tests\Extension;
use Symfony\Bridge\Twig\Extension\HttpFoundationExtension;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\RequestContext;
class HttpFoundationExtensionTest extends \PHPUnit_Framework_TestCase
{
@@ -43,6 +44,49 @@ class HttpFoundationExtensionTest extends \PHPUnit_Framework_TestCase
);
}
+ /**
+ * @dataProvider getGenerateAbsoluteUrlRequestContextData
+ */
+ public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected)
+ {
+ if (!class_exists('Symfony\Component\Routing\RequestContext')) {
+ $this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.');
+ }
+
+ $requestContext = new RequestContext($baseUrl, 'GET', $host, $scheme, $httpPort, $httpsPort, $path);
+ $extension = new HttpFoundationExtension(new RequestStack(), $requestContext);
+
+ $this->assertEquals($expected, $extension->generateAbsoluteUrl($path));
+ }
+
+ /**
+ * @dataProvider getGenerateAbsoluteUrlRequestContextData
+ */
+ public function testGenerateAbsoluteUrlWithoutRequestAndRequestContext($path)
+ {
+ if (!class_exists('Symfony\Component\Routing\RequestContext')) {
+ $this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.');
+ }
+
+ $extension = new HttpFoundationExtension(new RequestStack());
+
+ $this->assertEquals($path, $extension->generateAbsoluteUrl($path));
+ }
+
+ public function getGenerateAbsoluteUrlRequestContextData()
+ {
+ return array(
+ array('/foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo.png'),
+ array('foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo/foo.png'),
+ array('foo.png', '/foo/bar/', 'localhost', 'http', 80, 443, 'http://localhost/foo/bar/foo.png'),
+ array('/foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo.png'),
+ array('foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo/foo.png'),
+ array('foo.png', '/foo/bar/', 'localhost', 'https', 80, 443, 'https://localhost/foo/bar/foo.png'),
+ array('/foo.png', '/foo', 'localhost', 'http', 443, 80, 'http://localhost:443/foo.png'),
+ array('/foo.png', '/foo', 'localhost', 'https', 443, 80, 'https://localhost:80/foo.png'),
+ );
+ }
+
public function testGenerateAbsoluteUrlWithScriptFileName()
{
$request = Request::create('http://localhost/app/web/app_dev.php');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php
index 23a4460179..d8c60bcb9b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php
@@ -29,7 +29,13 @@ abstract class AbstractConfigCommand extends ContainerDebugCommand
{
$headers = array('Bundle name', 'Extension alias');
$rows = array();
- foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) {
+
+ $bundles = $this->getContainer()->get('kernel')->getBundles();
+ usort($bundles, function($bundleA, $bundleB) {
+ return strcmp($bundleA->getName(), $bundleB->getName());
+ });
+
+ foreach ($bundles as $bundle) {
$extension = $bundle->getContainerExtension();
$rows[] = array($bundle->getName(), $extension ? $extension->getAlias() : '');
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index a638daeb8a..b2df7917a9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -383,7 +383,12 @@ class Configuration implements ConfigurationInterface
->prototype('array')
->fixXmlConfig('base_url')
->children()
- ->scalarNode('version')->defaultNull()->end()
+ ->scalarNode('version')
+ ->beforeNormalization()
+ ->ifTrue(function ($v) { return '' === $v; })
+ ->then(function ($v) { return; })
+ ->end()
+ ->end()
->scalarNode('version_format')->defaultNull()->end()
->scalarNode('base_path')->defaultValue('')->end()
->arrayNode('base_urls')
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 7d8afee62b..d05f122794 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -568,7 +568,7 @@ class FrameworkExtension extends Extension
$namedPackages = array();
foreach ($config['packages'] as $name => $package) {
- if (null === $package['version']) {
+ if (!array_key_exists('version', $package)) {
$version = $defaultVersion;
} else {
$format = $package['version_format'] ?: $config['version_format'];
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
index e3532a7747..1055251004 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/assets.php
@@ -20,6 +20,10 @@ $container->loadFromExtension('framework', array(
'bar' => array(
'base_urls' => array('https://bar2.example.com'),
),
+ 'bar_null_version' => array(
+ 'version' => null,
+ 'base_urls' => array('https://bar3.example.com'),
+ ),
),
),
));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
index e39e15f900..3e057d5b90 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/assets.xml
@@ -18,6 +18,9 @@
https://bar2.example.com
+
+ https://bar3.example.com
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
index 193dc59dfb..d3285ff581 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/assets.yml
@@ -14,3 +14,6 @@ framework:
version_format: %%s-%%s
bar:
base_urls: ["https://bar2.example.com"]
+ bar_null_version:
+ version: null
+ base_urls: "https://bar3.example.com"
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index f6be36dae8..9c66a6761a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -209,7 +209,7 @@ abstract class FrameworkExtensionTest extends TestCase
// packages
$packages = $packages->getArgument(1);
- $this->assertCount(4, $packages);
+ $this->assertCount(5, $packages);
$package = $container->getDefinition($packages['images_path']);
$this->assertPathPackage($container, $package, '/foo', 'SomeVersionScheme', '%%s?version=%%s');
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
index c6aef2b99c..af293a7b63 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
@@ -18,6 +18,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
abstract class CompleteConfigurationTest extends \PHPUnit_Framework_TestCase
{
+ private static $containerCache = array();
+
abstract protected function loadFromFile(ContainerBuilder $container, $file);
public function testRolesHierarchy()
@@ -255,6 +257,9 @@ abstract class CompleteConfigurationTest extends \PHPUnit_Framework_TestCase
protected function getContainer($file)
{
+ if (isset(self::$containerCache[$file])) {
+ return self::$containerCache[$file];
+ }
$container = new ContainerBuilder();
$security = new SecurityExtension();
$container->registerExtension($security);
@@ -267,6 +272,6 @@ abstract class CompleteConfigurationTest extends \PHPUnit_Framework_TestCase
$container->getCompilerPassConfig()->setRemovingPasses(array());
$container->compile();
- return $container;
+ return self::$containerCache[$file] = $container;
}
}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
index bd1635ed87..55182c083a 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
@@ -112,6 +112,7 @@
+
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
index 84476a1977..66055a4eca 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
@@ -101,7 +101,7 @@
var request = requestStack[i];
var row = document.createElement('tr');
- rows.appendChild(row);
+ rows.insertBefore(row, rows.firstChild);
var methodCell = document.createElement('td');
if (request.error) {
diff --git a/src/Symfony/Component/HttpFoundation/ServerBag.php b/src/Symfony/Component/HttpFoundation/ServerBag.php
index fa1cb2fc9f..0d38c08ac0 100644
--- a/src/Symfony/Component/HttpFoundation/ServerBag.php
+++ b/src/Symfony/Component/HttpFoundation/ServerBag.php
@@ -86,6 +86,10 @@ class ServerBag extends ParameterBag
}
}
+ if (isset($headers['AUTHORIZATION'])) {
+ return $headers;
+ }
+
// PHP_AUTH_USER/PHP_AUTH_PW
if (isset($headers['PHP_AUTH_USER'])) {
$headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']);
diff --git a/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php
index 20773c4d7a..41e44e1005 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/ServerBagTest.php
@@ -151,4 +151,19 @@ class ServerBagTest extends \PHPUnit_Framework_TestCase
'AUTHORIZATION' => $headerContent,
), $bag->getHeaders());
}
+
+ /**
+ * @see https://github.com/symfony/symfony/issues/17345
+ */
+ public function testItDoesNotOverwriteTheAuthorizationHeaderIfItIsAlreadySet()
+ {
+ $headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo';
+ $bag = new ServerBag(array('PHP_AUTH_USER' => 'foo', 'HTTP_AUTHORIZATION' => $headerContent));
+
+ $this->assertEquals(array(
+ 'AUTHORIZATION' => $headerContent,
+ 'PHP_AUTH_USER' => 'foo',
+ 'PHP_AUTH_PW' => '',
+ ), $bag->getHeaders());
+ }
}
diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php
index a08a37ec98..0e0b4ee01e 100644
--- a/src/Symfony/Component/Yaml/Inline.php
+++ b/src/Symfony/Component/Yaml/Inline.php
@@ -105,7 +105,7 @@ class Inline
return 'null';
case is_object($value):
if ($objectSupport) {
- return '!!php/object:'.serialize($value);
+ return '!php/object:'.serialize($value);
}
if ($exceptionOnInvalidType) {
@@ -476,6 +476,16 @@ class Inline
return (string) substr($scalar, 5);
case 0 === strpos($scalar, '! '):
return (int) self::parseScalar(substr($scalar, 2));
+ case 0 === strpos($scalar, '!php/object:'):
+ if (self::$objectSupport) {
+ return unserialize(substr($scalar, 12));
+ }
+
+ if (self::$exceptionOnInvalidType) {
+ throw new ParseException('Object support when parsing a YAML file has been disabled.');
+ }
+
+ return;
case 0 === strpos($scalar, '!!php/object:'):
if (self::$objectSupport) {
return unserialize(substr($scalar, 13));
diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php
index 5b9cb25017..2a0df692b3 100644
--- a/src/Symfony/Component/Yaml/Tests/DumperTest.php
+++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php
@@ -180,7 +180,7 @@ EOF;
{
$dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true);
- $this->assertEquals('{ foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects');
+ $this->assertEquals('{ foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects');
}
public function testObjectSupportDisabledButNoExceptions()
diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php
index f032d1ff97..81f97916a8 100644
--- a/src/Symfony/Component/Yaml/Tests/ParserTest.php
+++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php
@@ -426,15 +426,19 @@ foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";}
bar: 1
EOF;
$this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects');
- }
- public function testObjectSupportDisabledButNoExceptions()
- {
$input = <<assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects');
+ }
+ /**
+ * @dataProvider invalidDumpedObjectProvider
+ */
+ public function testObjectSupportDisabledButNoExceptions($input)
+ {
$this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects');
}
@@ -470,11 +474,29 @@ EOF;
}
/**
+ * @dataProvider invalidDumpedObjectProvider
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/
- public function testObjectsSupportDisabledWithExceptions()
+ public function testObjectsSupportDisabledWithExceptions($yaml)
{
- $this->parser->parse('foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";}', true, false);
+ $this->parser->parse($yaml, true, false);
+ }
+
+ public function invalidDumpedObjectProvider()
+ {
+ $yamlTag = << array($yamlTag),
+ 'local-tag' => array($localTag),
+ );
}
/**