diff --git a/CHANGELOG-3.2.md b/CHANGELOG-3.2.md
index de3c3fd9977b5..1a4d44e19981e 100644
--- a/CHANGELOG-3.2.md
+++ b/CHANGELOG-3.2.md
@@ -7,6 +7,22 @@ in 3.2 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.2.0...v3.2.1
+* 3.2.12 (2017-07-17)
+
+ * bug #23549 [PropertyInfo] conflict for phpdocumentor/reflection-docblock 3.2 (xabbuh)
+ * security #23507 [Security] validate empty passwords again (xabbuh)
+ * bug #23526 [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content (jnvsor)
+ * bug #23540 Disable inlining deprecated services (alekitto)
+ * bug #23468 [DI] Handle root namespace in service definitions (ro0NL)
+ * bug #23256 [Security] Fix authentication.failure event not dispatched on AccountStatusException (chalasr)
+ * bug #23461 Use rawurlencode() to transform the Cookie into a string (javiereguiluz)
+ * bug #23459 [TwigBundle] allow to configure custom formats in XML configs (xabbuh)
+ * bug #23460 Don't display the Symfony debug toolbar when printing the page (javiereguiluz)
+ * bug #23469 [FrameworkBundle] do not wire namespaces for the ArrayAdapter (xabbuh)
+ * bug #23417 [DI][Security] Prevent unwanted deprecation notices when using Expression Languages (dunglas)
+ * bug #23261 Fixed absolute url generation for query strings and hash urls (alexander-schranz)
+ * bug #23398 [Filesystem] Dont copy perms when origin is remote (nicolas-grekas)
+
* 3.2.11 (2017-07-05)
* bug #23390 [Cache] Handle APCu failures gracefully (nicolas-grekas)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 3432439481471..9cf36e6beb382 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -70,9 +70,9 @@ Symfony is the result of the work of many people who made the code better
- Deni
- Henrik Westphal (snc)
- Dariusz Górecki (canni)
+ - Jáchym Toušek (enumag)
- Titouan Galopin (tgalopin)
- Douglas Greenshields (shieldo)
- - Jáchym Toušek (enumag)
- Konstantin Myakshin (koc)
- Lee McDermott
- Brandon Turner
@@ -99,11 +99,12 @@ Symfony is the result of the work of many people who made the code better
- Baptiste Clavié (talus)
- Vladimir Reznichenko (kalessil)
- marc.weistroff
+ - Yonel Ceruto González (yonelceruto)
- lenar
- Włodzimierz Gajda (gajdaw)
- - Yonel Ceruto González (yonelceruto)
- Alexander Schwenn (xelaris)
- Jacob Dreesen (jdreesen)
+ - Tobias Nyholm (tobias)
- Florian Voutzinos (florianv)
- Colin Frei
- Adrien Brault (adrienbrault)
@@ -111,7 +112,6 @@ Symfony is the result of the work of many people who made the code better
- Peter Kokot (maastermedia)
- David Buchmann (dbu)
- excelwebzone
- - Tobias Nyholm (tobias)
- Tomáš Votruba (tomas_votruba)
- Fabien Pennequin (fabienpennequin)
- Gordon Franke (gimler)
@@ -133,12 +133,15 @@ Symfony is the result of the work of many people who made the code better
- Guilherme Blanco (guilhermeblanco)
- Pablo Godel (pgodel)
- Jérémie Augustin (jaugustin)
+ - Dany Maillard (maidmaid)
- Andréia Bohner (andreia)
- Rafael Dohms (rdohms)
- Arnaud Kleinpeter (nanocom)
- jwdeitch
+ - David Maicher (dmaicher)
- Mikael Pajunen
- Joel Wurtz (brouznouf)
+ - Grégoire Paris (greg0ire)
- Philipp Wahala (hifi)
- Vyacheslav Pavlov
- Richard van Laak (rvanlaak)
@@ -147,11 +150,9 @@ Symfony is the result of the work of many people who made the code better
- Thomas Rabaix (rande)
- Rouven Weßling (realityking)
- Teoh Han Hui (teohhanhui)
- - David Maicher (dmaicher)
- Jérôme Vasseur (jvasseur)
- Clemens Tolboom
- Helmer Aaviksoo
- - Grégoire Paris (greg0ire)
- Hiromi Hishida (77web)
- Matthieu Ouellette-Vachon (maoueh)
- Michał Pipa (michal.pipa)
@@ -236,7 +237,6 @@ Symfony is the result of the work of many people who made the code better
- Arjen Brouwer (arjenjb)
- Katsuhiro OGAWA
- Patrick McDougle (patrick-mcdougle)
- - Dany Maillard (maidmaid)
- Alif Rachmawadi
- Kristen Gilden (kgilden)
- Pierre-Yves LEBECQ (pylebecq)
@@ -622,6 +622,7 @@ Symfony is the result of the work of many people who made the code better
- develop
- ReenExe
- Mark Sonnabaum
+ - Maxime Veber (nek-)
- Richard Quadling
- jochenvdv
- Arturas Smorgun (asarturas)
@@ -644,6 +645,7 @@ Symfony is the result of the work of many people who made the code better
- Trent Steel (trsteel88)
- Yuen-Chi Lian
- Besnik Br
+ - Jose Gonzalez
- Dariusz Ruminski
- Joshua Nye
- Claudio Zizza
@@ -1083,7 +1085,6 @@ Symfony is the result of the work of many people who made the code better
- Max Summe
- WedgeSama
- Felds Liscia
- - Maxime Veber (nek-)
- Sullivan SENECHAL
- Tadcka
- Beth Binkovitz
@@ -1094,12 +1095,12 @@ Symfony is the result of the work of many people who made the code better
- Tomaz Ahlin
- Marcus Stöhr (dafish)
- Emmanuel Vella (emmanuel.vella)
+ - Adam Szaraniec (mimol)
- Carsten Nielsen (phreaknerd)
- Mathieu Rochette
- Jay Severson
- René Kerner
- Nathaniel Catchpole
- - Jose Gonzalez
- Adrien Samson (adriensamson)
- Samuel Gordalina (gordalina)
- Max Romanovsky (maxromanovsky)
@@ -1260,6 +1261,7 @@ Symfony is the result of the work of many people who made the code better
- Aarón Nieves Fernández
- Mike Meier
- Kirill Saksin
+ - Julien Pauli
- Koalabaerchen
- michalmarcinkowski
- Warwick
@@ -1307,6 +1309,7 @@ Symfony is the result of the work of many people who made the code better
- klemens
- dened
- Dmitry Korotovsky
+ - mcorteel
- Michael van Tricht
- Sam Ward
- Walther Lalk
@@ -1337,6 +1340,7 @@ Symfony is the result of the work of many people who made the code better
- Jan Marek (janmarek)
- Mark de Haan (markdehaan)
- Dan Patrick (mdpatrick)
+ - Pedro Magalhães (pmmaga)
- Rares Vlaseanu (raresvla)
- tante kinast (tante)
- Vincent LEFORT (vlefort)
@@ -1544,6 +1548,7 @@ Symfony is the result of the work of many people who made the code better
- Abdulkadir N. A.
- Yevgen Kovalienia
- Lebnik
+ - Shude
- Ondřej Führer
- Sema
- Elan Ruusamäe
diff --git a/composer.json b/composer.json
index 75e9c916370b2..8730dd64159e8 100644
--- a/composer.json
+++ b/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": ">=5.5.9",
+ "ext-xml": "*",
"doctrine/common": "~2.4",
"twig/twig": "~1.34|~2.4",
"psr/cache": "~1.0",
@@ -94,7 +95,7 @@
"sensio/framework-extra-bundle": "^3.0.2"
},
"conflict": {
- "phpdocumentor/reflection-docblock": "<3.0",
+ "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0",
"phpdocumentor/type-resolver": "<0.2.0",
"phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0"
},
diff --git a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
index 90b515ee320ba..0dad40cfa0a3f 100644
--- a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php
@@ -72,6 +72,13 @@ public function generateAbsoluteUrl($path)
$port = ':'.$this->requestContext->getHttpsPort();
}
+ if ('#' === $path[0]) {
+ $queryString = $this->requestContext->getQueryString();
+ $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path;
+ } elseif ('?' === $path[0]) {
+ $path = $this->requestContext->getPathInfo().$path;
+ }
+
if ('/' !== $path[0]) {
$path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path;
}
@@ -82,6 +89,12 @@ public function generateAbsoluteUrl($path)
return $path;
}
+ if ('#' === $path[0]) {
+ $path = $request->getRequestUri().$path;
+ } elseif ('?' === $path[0]) {
+ $path = $request->getPathInfo().$path;
+ }
+
if (!$path || '/' !== $path[0]) {
$prefix = $request->getPathInfo();
$last = strlen($prefix) - 1;
diff --git a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php
index 9718c29cdb689..9d28b8c237d16 100644
--- a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php
+++ b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php
@@ -20,16 +20,19 @@
*/
class TwigRenderer extends FormRenderer implements TwigRendererInterface
{
- /**
- * @var TwigRendererEngineInterface
- */
- private $engine;
-
public function __construct(TwigRendererEngineInterface $engine, CsrfTokenManagerInterface $csrfTokenManager = null)
{
parent::__construct($engine, $csrfTokenManager);
+ }
- $this->engine = $engine;
+ /**
+ * Returns the engine used by this renderer.
+ *
+ * @return TwigRendererEngineInterface The renderer engine
+ */
+ public function getEngine()
+ {
+ return parent::getEngine();
}
/**
@@ -37,6 +40,6 @@ public function __construct(TwigRendererEngineInterface $engine, CsrfTokenManage
*/
public function setEnvironment(Environment $environment)
{
- $this->engine->setEnvironment($environment);
+ $this->getEngine()->setEnvironment($environment);
}
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
index 8f0c66ad78bb4..fcff0c0e1b93b 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php
@@ -42,6 +42,15 @@ public function getGenerateAbsoluteUrlData()
array('http://example.com/baz', 'http://example.com/baz', '/'),
array('https://example.com/baz', 'https://example.com/baz', '/'),
array('//example.com/baz', '//example.com/baz', '/'),
+
+ array('http://localhost/foo/bar?baz', '?baz', '/foo/bar'),
+ array('http://localhost/foo/bar?baz=1', '?baz=1', '/foo/bar?foo=1'),
+ array('http://localhost/foo/baz?baz=1', 'baz?baz=1', '/foo/bar?foo=1'),
+
+ array('http://localhost/foo/bar#baz', '#baz', '/foo/bar'),
+ array('http://localhost/foo/bar?0#baz', '#baz', '/foo/bar?0'),
+ array('http://localhost/foo/bar?baz=1#baz', '?baz=1#baz', '/foo/bar?foo=1'),
+ array('http://localhost/foo/baz?baz=1#baz', 'baz?baz=1#baz', '/foo/bar?foo=1'),
);
}
diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json
index e5fe655296473..512639fa7e2e4 100644
--- a/src/Symfony/Bundle/DebugBundle/composer.json
+++ b/src/Symfony/Bundle/DebugBundle/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": ">=5.5.9",
+ "ext-xml": "*",
"symfony/http-kernel": "~2.8|~3.0",
"symfony/twig-bridge": "~2.8|~3.0",
"symfony/var-dumper": "~2.8|~3.0"
diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index efee66b41cecf..c1eb01d3284e3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -21,7 +21,8 @@ CHANGELOG
* Deprecated using core form types without dependencies as services
* Added `Symfony\Component\HttpHernel\DataCollector\RequestDataCollector::onKernelResponse()`
* Added `Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector`
- * Deprecated service `serializer.mapping.cache.apc` (use `serializer.mapping.cache.doctrine.apc` instead)
+ * The `framework.serializer.cache` option and the service `serializer.mapping.cache.apc` have been
+ deprecated. APCu should now be automatically used when available.
3.0.0
-----
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
index db1430eb49b13..eda6f936bf7b5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -70,7 +71,7 @@ public function process(ContainerBuilder $container)
}
$i = 0;
foreach ($attributes as $attr) {
- if (isset($tags[0][$attr])) {
+ if (isset($tags[0][$attr]) && ('namespace' !== $attr || ArrayAdapter::class !== $adapter->getClass())) {
$pool->replaceArgument($i++, $tags[0][$attr]);
}
unset($tags[0][$attr]);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
index 6fe6b30eb36c4..e9b9bbc778cac 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
@@ -13,6 +13,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass;
+use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
@@ -49,6 +50,24 @@ public function testNamespaceArgumentIsReplaced()
$this->assertSame('D07rhFx97S', $cachePool->getArgument(0));
}
+ public function testNamespaceArgumentIsNotReplacedIfArrayAdapterIsUsed()
+ {
+ $container = new ContainerBuilder();
+ $container->setParameter('kernel.environment', 'prod');
+ $container->setParameter('kernel.name', 'app');
+ $container->setParameter('kernel.root_dir', 'foo');
+
+ $container->register('cache.adapter.array', ArrayAdapter::class)->addArgument(0);
+
+ $cachePool = new DefinitionDecorator('cache.adapter.array');
+ $cachePool->addTag('cache.pool');
+ $container->setDefinition('app.cache_pool', $cachePool);
+
+ $this->cachePoolPass->process($container);
+
+ $this->assertCount(0, $container->getDefinition('app.cache_pool')->getArguments());
+ }
+
public function testArgsAreReplaced()
{
$container = new ContainerBuilder();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
index fb5395ea6d26d..fd9ed77b2f7ab 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php
@@ -25,6 +25,10 @@ public function testRedirectWhenNoSlash()
$coll->add('foo', new Route('/foo/'));
$matcher = new RedirectableUrlMatcher($coll, $context = new RequestContext());
+ $parameters = $matcher->match('/foo');
+ if ('foo' === $parameters['_route']) {
+ $parameters['_route'] = null; // FC with behavior on 3.4
+ }
$this->assertEquals(array(
'_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction',
@@ -35,7 +39,7 @@ public function testRedirectWhenNoSlash()
'httpsPort' => $context->getHttpsPort(),
'_route' => null,
),
- $matcher->match('/foo')
+ $parameters
);
}
diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json
index dbcec82819615..4759d44a2e5f5 100644
--- a/src/Symfony/Bundle/SecurityBundle/composer.json
+++ b/src/Symfony/Bundle/SecurityBundle/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": ">=5.5.9",
+ "ext-xml": "*",
"symfony/security": "~3.2",
"symfony/http-kernel": "~3.2",
"symfony/polyfill-php70": "~1.0"
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd
index 3314091a08802..61b57798b27cf 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd
@@ -9,6 +9,8 @@
+
+
@@ -26,6 +28,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php
new file mode 100644
index 0000000000000..630a9a9edc01a
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php
@@ -0,0 +1,14 @@
+loadFromExtension('twig', array(
+ 'date' => array(
+ 'format' => 'Y-m-d',
+ 'interval_format' => '%d',
+ 'timezone' => 'Europe/Berlin',
+ ),
+ 'number_format' => array(
+ 'decimals' => 2,
+ 'decimal_point' => ',',
+ 'thousands_separator' => '.',
+ ),
+));
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml
new file mode 100644
index 0000000000000..1ab39e49229cd
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml
new file mode 100644
index 0000000000000..290921630f9e6
--- /dev/null
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml
@@ -0,0 +1,9 @@
+twig:
+ date:
+ format: Y-m-d
+ interval_format: '%d'
+ timezone: Europe/Berlin
+ number_format:
+ decimals: 2
+ decimal_point: ','
+ thousands_separator: .
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
index d2fb85bd921a1..df3d11945622f 100644
--- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
@@ -116,6 +116,26 @@ public function testLoadDefaultTemplateEscapingGuesserConfiguration($format)
$this->assertEquals('name', $options['autoescape']);
}
+ /**
+ * @dataProvider getFormats
+ */
+ public function testLoadCustomDateFormats($fileFormat)
+ {
+ $container = $this->createContainer();
+ $container->registerExtension(new TwigExtension());
+ $this->loadFromFile($container, 'formats', $fileFormat);
+ $this->compileContainer($container);
+
+ $environmentConfigurator = $container->getDefinition('twig.configurator.environment');
+
+ $this->assertSame('Y-m-d', $environmentConfigurator->getArgument(0));
+ $this->assertSame('%d', $environmentConfigurator->getArgument(1));
+ $this->assertSame('Europe/Berlin', $environmentConfigurator->getArgument(2));
+ $this->assertSame(2, $environmentConfigurator->getArgument(3));
+ $this->assertSame(',', $environmentConfigurator->getArgument(4));
+ $this->assertSame('.', $environmentConfigurator->getArgument(5));
+ }
+
public function testGlobalsWithDifferentTypesAndValues()
{
$globals = array(
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php
index 37f47df6a6e40..7ebd04b574c22 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php
+++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php
@@ -128,34 +128,6 @@ public function panelAction(Request $request, $token)
)), 200, array('Content-Type' => 'text/html'));
}
- /**
- * Displays information page.
- *
- * @param Request $request The current HTTP Request
- * @param string $about The about message
- *
- * @return Response A Response instance
- *
- * @throws NotFoundHttpException
- */
- public function infoAction(Request $request, $about)
- {
- if (null === $this->profiler) {
- throw new NotFoundHttpException('The profiler must be enabled.');
- }
-
- $this->profiler->disable();
-
- if (null !== $this->cspHandler) {
- $this->cspHandler->disableCsp();
- }
-
- return new Response($this->twig->render('@WebProfiler/Profiler/info.html.twig', array(
- 'about' => $about,
- 'request' => $request,
- )), 200, array('Content-Type' => 'text/html'));
- }
-
/**
* Renders the Web Debug Toolbar.
*
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml
index 1a4bd39c621a6..0be717b19d6e7 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml
@@ -16,10 +16,6 @@
web_profiler.controller.profiler:searchBarAction
-
- web_profiler.controller.profiler:infoAction
-
-
web_profiler.controller.profiler:phpinfoAction
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig
index ef381fe4a73a7..0227532e1208a 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig
@@ -1,25 +1,10 @@
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
{% set messages = {
- 'purge' : {
- status: 'success',
- title: 'The profiler database was purged successfully',
- message: 'Now you need to browse some pages with the Symfony Profiler enabled to collect data.'
- },
'no_token' : {
status: 'error',
title: (token|default('') == 'latest') ? 'There are no profiles' : 'Token not found',
message: (token|default('') == 'latest') ? 'No profiles found in the database.' : 'Token "' ~ token|default('') ~ '" was not found in the database.'
- },
- 'upload_error' : {
- status: 'error',
- title: 'A problem occurred when uploading the data',
- message: 'No file given or the file was not uploaded successfully.'
- },
- 'already_exists' : {
- status: 'error',
- title: 'A problem occurred when uploading the data',
- message: 'The token already exists in the database.'
}
} %}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig
index 590d030c7a55a..862b7f43c6ec6 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig
@@ -552,3 +552,10 @@
padding: 5px 0;
margin-right: 10px;
}
+
+/***** Media query print: Do not print the Toolbar. *****/
+@media print {
+ .sf-toolbar {
+ display: none;
+ }
+}
diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php
index 42f184d532e02..c042c6a525295 100644
--- a/src/Symfony/Component/BrowserKit/Cookie.php
+++ b/src/Symfony/Component/BrowserKit/Cookie.php
@@ -62,7 +62,7 @@ public function __construct($name, $value, $expires = null, $path = null, $domai
$this->rawValue = $value;
} else {
$this->value = $value;
- $this->rawValue = urlencode($value);
+ $this->rawValue = rawurlencode($value);
}
$this->name = $name;
$this->path = empty($path) ? '/' : $path;
diff --git a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php
index 38ea81220bb2c..2f5a08d104143 100644
--- a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php
+++ b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php
@@ -16,6 +16,21 @@
class CookieTest extends TestCase
{
+ public function testToString()
+ {
+ $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
+ $this->assertEquals('foo=bar; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');
+
+ $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
+ $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)');
+
+ $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
+ $this->assertEquals('foo=; expires=Thu, 01 Jan 1970 00:00:01 GMT; domain=.myfoodomain.com; path=/admin/; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
+
+ $cookie = new Cookie('foo', 'bar', 0, '/', '');
+ $this->assertEquals('foo=bar; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; httponly', (string) $cookie);
+ }
+
/**
* @dataProvider getTestsForToFromString
*/
diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
index 84bb841d85df2..628638ea969c4 100644
--- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
@@ -39,6 +39,10 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface
*/
protected $maxIdLength;
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ */
protected function __construct($namespace = '', $defaultLifetime = 0)
{
$this->namespace = '' === $namespace ? '' : $this->getId($namespace).':';
@@ -81,6 +85,15 @@ function ($deferred, $namespace, &$expiredIds) {
);
}
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ * @param string $version
+ * @param string $directory
+ * @param LoggerInterface|null $logger
+ *
+ * @return AdapterInterface
+ */
public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null)
{
if (null === self::$apcuSupported) {
@@ -139,7 +152,7 @@ abstract protected function doHave($id);
/**
* Deletes all items in the pool.
*
- * @param string The prefix used for all identifiers managed by this pool
+ * @param string $namespace The prefix used for all identifiers managed by this pool
*
* @return bool True if the pool was successfully cleared, false otherwise
*/
diff --git a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
index ad3aadf1a5257..08179dd8faf5c 100644
--- a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
@@ -24,6 +24,13 @@ public static function isSupported()
return function_exists('apcu_fetch') && ini_get('apc.enabled');
}
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ * @param string|null $version
+ *
+ * @throws CacheException if APCu is not enabled
+ */
public function __construct($namespace = '', $defaultLifetime = 0, $version = null)
{
if (!static::isSupported()) {
diff --git a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php
index ed91bf56cd0e5..70426b5dd5125 100644
--- a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php
@@ -20,6 +20,11 @@ class DoctrineAdapter extends AbstractAdapter
{
private $provider;
+ /**
+ * @param CacheProvider $provider
+ * @param string $namespace
+ * @param int $defaultLifetime
+ */
public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0)
{
parent::__construct('', $defaultLifetime);
diff --git a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php
index 1c62641cf6d67..c7422d36a2164 100644
--- a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php
@@ -20,6 +20,11 @@ class FilesystemAdapter extends AbstractAdapter
{
use FilesystemAdapterTrait;
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ * @param string|null $directory
+ */
public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
{
parent::__construct('', $defaultLifetime);
diff --git a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php
index 88107cb9899dc..2ce605a40fca0 100644
--- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php
@@ -29,6 +29,13 @@ public static function isSupported()
return function_exists('opcache_invalidate') && ini_get('opcache.enable');
}
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ * @param string|null $directory
+ *
+ * @throws CacheException if OPcache is not enabled
+ */
public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
{
if (!static::isSupported()) {
diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
index 2ed895c873a3e..4f37ffd731931 100644
--- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php
@@ -26,6 +26,11 @@ class ProxyAdapter implements AdapterInterface
private $createCacheItem;
private $poolHash;
+ /**
+ * @param CacheItemPoolInterface $pool
+ * @param string $namespace
+ * @param int $defaultLifetime
+ */
public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defaultLifetime = 0)
{
$this->pool = $pool;
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php
index 50206bb278b52..8c6eacf4bbec5 100644
--- a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php
+++ b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Cache\Tests\Adapter;
+use Psr\Log\NullLogger;
use Symfony\Component\Cache\Adapter\ApcuAdapter;
class ApcuAdapterTest extends AdapterTestCase
@@ -23,9 +24,14 @@ class ApcuAdapterTest extends AdapterTestCase
public function createCachePool($defaultLifetime = 0)
{
- if (!function_exists('apcu_fetch') || !ini_get('apc.enabled') || ('cli' === PHP_SAPI && !ini_get('apc.enable_cli'))) {
+ if (!function_exists('apcu_fetch') || !ini_get('apc.enabled')) {
$this->markTestSkipped('APCu extension is required.');
}
+ if ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) {
+ if ('testWithCliSapi' !== $this->getName()) {
+ $this->markTestSkipped('APCu extension is required.');
+ }
+ }
if ('\\' === DIRECTORY_SEPARATOR) {
$this->markTestSkipped('Fails transiently on Windows.');
}
@@ -70,4 +76,24 @@ public function testVersion()
$this->assertFalse($item->isHit());
$this->assertNull($item->get());
}
+
+ public function testWithCliSapi()
+ {
+ try {
+ // disable PHPUnit error handler to mimic a production environment
+ $isCalled = false;
+ set_error_handler(function () use (&$isCalled) {
+ $isCalled = true;
+ });
+ $pool = new ApcuAdapter(str_replace('\\', '.', __CLASS__));
+ $pool->setLogger(new NullLogger());
+
+ $item = $pool->getItem('foo');
+ $item->isHit();
+ $pool->save($item->set('bar'));
+ $this->assertFalse($isCalled);
+ } finally {
+ restore_error_handler();
+ }
+ }
}
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
index a4e2e041b24fe..3bec493e91848 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
@@ -111,7 +111,7 @@ private function isInlineableDefinition($id, Definition $definition)
return true;
}
- if ($definition->isPublic() || $definition->isLazy()) {
+ if ($definition->isDeprecated() || $definition->isPublic() || $definition->isLazy()) {
return false;
}
diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php
index 2f96abca34097..1ed239b939747 100644
--- a/src/Symfony/Component/DependencyInjection/Container.php
+++ b/src/Symfony/Component/DependencyInjection/Container.php
@@ -28,16 +28,6 @@
*
* Parameter and service keys are case insensitive.
*
- * A service id can contain lowercased letters, digits, underscores, and dots.
- * Underscores are used to separate words, and dots to group services
- * under namespaces:
- *
- *
- * - request
- * - mysql_session_storage
- * - symfony.mysql_session_storage
- *
- *
* A service can also be defined by creating a method named
* getXXXService(), where XXX is the camelized version of the id:
*
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index dd514962ea47c..2b7d0b2a6a3fe 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -389,15 +389,9 @@ private function addServiceReturn($id, $definition)
*/
private function addServiceInstance($id, Definition $definition)
{
- $class = $definition->getClass();
-
- if ('\\' === substr($class, 0, 1)) {
- $class = substr($class, 1);
- }
-
- $class = $this->dumpValue($class);
+ $class = $this->dumpValue($definition->getClass());
- if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
+ if (0 === strpos($class, "'") && false === strpos($class, '$') && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id));
}
@@ -1453,11 +1447,13 @@ private function dumpLiteralClass($class)
if (false !== strpos($class, '$')) {
return sprintf('${($_ = %s) && false ?: "_"}', $class);
}
- if (0 !== strpos($class, "'") || !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
+ if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) {
throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a'));
}
- return '\\'.substr(str_replace('\\\\', '\\', $class), 1, -1);
+ $class = substr(str_replace('\\\\', '\\', $class), 1, -1);
+
+ return 0 === strpos($class, '\\') ? $class : '\\'.$class;
}
/**
diff --git a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php
index acc97bcf4973d..d80985fa670e5 100644
--- a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php
+++ b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\DependencyInjection;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
-use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
/**
* Adds some function to the default ExpressionLanguage.
@@ -23,7 +22,10 @@
*/
class ExpressionLanguage extends BaseExpressionLanguage
{
- public function __construct(ParserCacheInterface $cache = null, array $providers = array())
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($cache = null, array $providers = array())
{
// prepend the default provider to let users override it easily
array_unshift($providers, new ExpressionLanguageProvider());
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
index f8693684b8e12..e8673cee950c9 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
@@ -823,6 +823,27 @@ public function testAutowiring()
$this->assertEquals('a', (string) $container->getDefinition('b')->getArgument(0));
}
+
+ /**
+ * This test checks the trigger of a deprecation note and should not be removed in major releases.
+ *
+ * @group legacy
+ * @expectedDeprecation The "foo" service is deprecated. You should stop using it, as it will soon be removed.
+ */
+ public function testPrivateServiceTriggersDeprecation()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', 'stdClass')
+ ->setPublic(false)
+ ->setDeprecated(true);
+ $container->register('bar', 'stdClass')
+ ->setPublic(true)
+ ->setProperty('foo', new Reference('foo'));
+
+ $container->compile();
+
+ $container->get('bar');
+ }
}
class FooClass
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
index 8d5eda9ce5fe8..4b31cb6fe0082 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
@@ -144,8 +144,8 @@ public function testGetLegacyServiceIds()
public function testSet()
{
$sc = new Container();
- $sc->set('foo', $foo = new \stdClass());
- $this->assertSame($foo, $sc->get('foo'), '->set() sets a service');
+ $sc->set('._. \\o/', $foo = new \stdClass());
+ $this->assertSame($foo, $sc->get('._. \\o/'), '->set() sets a service');
}
public function testSetWithNullResetTheService()
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
index ee81219ef01d0..2ff01d120b169 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -424,4 +424,43 @@ public function testPrivateWithIgnoreOnInvalidReference()
$container = new \Symfony_DI_PhpDumper_Test_Private_With_Ignore_On_Invalid_Reference();
$this->assertInstanceOf('BazClass', $container->get('bar')->getBaz());
}
+
+ public function testDumpHandlesLiteralClassWithRootNamespace()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', '\\stdClass');
+
+ $dumper = new PhpDumper($container);
+ eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace')));
+
+ $container = new \Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace();
+
+ $this->assertInstanceOf('stdClass', $container->get('foo'));
+ }
+
+ /**
+ * This test checks the trigger of a deprecation note and should not be removed in major releases.
+ *
+ * @group legacy
+ * @expectedDeprecation The "foo" service is deprecated. You should stop using it, as it will soon be removed.
+ */
+ public function testPrivateServiceTriggersDeprecation()
+ {
+ $container = new ContainerBuilder();
+ $container->register('foo', 'stdClass')
+ ->setPublic(false)
+ ->setDeprecated(true);
+ $container->register('bar', 'stdClass')
+ ->setPublic(true)
+ ->setProperty('foo', new Reference('foo'));
+
+ $container->compile();
+
+ $dumper = new PhpDumper($container);
+ eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation')));
+
+ $container = new \Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation();
+
+ $container->get('bar');
+ }
}
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index 1a67a971358fe..9e3135460b700 100644
--- a/src/Symfony/Component/Filesystem/Filesystem.php
+++ b/src/Symfony/Component/Filesystem/Filesystem.php
@@ -37,7 +37,8 @@ class Filesystem
*/
public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
{
- if (stream_is_local($originFile) && !is_file($originFile)) {
+ $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
+ if ($originIsLocal && !is_file($originFile)) {
throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
}
@@ -68,11 +69,13 @@ public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
}
- // Like `cp`, preserve executable permission bits
- @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
+ if ($originIsLocal) {
+ // Like `cp`, preserve executable permission bits
+ @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
- if (stream_is_local($originFile) && $bytesCopied !== ($bytesOrigin = filesize($originFile))) {
- throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile);
+ if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
+ throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile);
+ }
}
}
}
diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php
index be13dab85e46d..492c6fbe75193 100644
--- a/src/Symfony/Component/HttpFoundation/Cookie.php
+++ b/src/Symfony/Component/HttpFoundation/Cookie.php
@@ -96,7 +96,7 @@ public function __toString()
if ('' === (string) $this->getValue()) {
$str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001);
} else {
- $str .= $this->isRaw() ? $this->getValue() : urlencode($this->getValue());
+ $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue());
if (0 !== $this->getExpiresTime()) {
$str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime());
diff --git a/src/Symfony/Component/HttpFoundation/RedirectResponse.php b/src/Symfony/Component/HttpFoundation/RedirectResponse.php
index 7435999a019f6..cb1c58e8999a5 100644
--- a/src/Symfony/Component/HttpFoundation/RedirectResponse.php
+++ b/src/Symfony/Component/HttpFoundation/RedirectResponse.php
@@ -87,7 +87,7 @@ public function setTargetUrl($url)
-
+
Redirecting to %1$s
diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
index c2d1c9b7527a7..3986a7e8f8796 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
@@ -160,6 +160,9 @@ public function testToString()
$cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
$this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie');
+ $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true);
+ $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)');
+
$cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com');
$this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
@@ -171,7 +174,7 @@ public function testRawCookie()
{
$cookie = new Cookie('foo', 'b a r', 0, '/', null, false, false);
$this->assertFalse($cookie->isRaw());
- $this->assertEquals('foo=b+a+r; path=/', (string) $cookie);
+ $this->assertEquals('foo=b%20a%20r; path=/', (string) $cookie);
$cookie = new Cookie('foo', 'b+a+r', 0, '/', null, false, false, true);
$this->assertTrue($cookie->isRaw());
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index bdfd2b2d9c4e7..d0acb4af856a4 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -58,11 +58,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface
protected $startTime;
protected $loadClassCache;
- const VERSION = '3.2.11';
- const VERSION_ID = 30211;
+ const VERSION = '3.2.12';
+ const VERSION_ID = 30212;
const MAJOR_VERSION = 3;
const MINOR_VERSION = 2;
- const RELEASE_VERSION = 11;
+ const RELEASE_VERSION = 12;
const EXTRA_VERSION = '';
const END_OF_MAINTENANCE = '07/2017';
diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php
index 9a306e533e006..e642e3c33715f 100644
--- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php
@@ -50,7 +50,7 @@ public function testDump()
);
$this->assertEquals($xDump, $dump);
- $this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";O:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize());
+ $this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";%c:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize());
$this->assertSame(0, $collector->getDumpsCount());
$this->assertSame('a:2:{i:0;b:0;i:1;s:5:"UTF-8";}', $collector->serialize());
}
diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json
index 23069a1e79870..f9df8807396c3 100644
--- a/src/Symfony/Component/PropertyInfo/composer.json
+++ b/src/Symfony/Component/PropertyInfo/composer.json
@@ -33,7 +33,7 @@
"doctrine/annotations": "~1.0"
},
"conflict": {
- "phpdocumentor/reflection-docblock": "<3.0",
+ "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0",
"phpdocumentor/type-resolver": "<0.2.0"
},
"suggest": {
diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
index 16de8daaeda93..4c0a7459d070c 100644
--- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
+++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
@@ -83,9 +83,9 @@ public function authenticate(TokenInterface $token)
break;
}
} catch (AccountStatusException $e) {
- $e->setToken($token);
+ $lastException = $e;
- throw $e;
+ break;
} catch (AuthenticationException $e) {
$lastException = $e;
}
diff --git a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php
index c2925af87121a..d4c8f33e06491 100644
--- a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php
+++ b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\Security\Core\Authorization;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
-use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
/**
* Adds some function to the default ExpressionLanguage.
@@ -23,7 +22,10 @@
*/
class ExpressionLanguage extends BaseExpressionLanguage
{
- public function __construct(ParserCacheInterface $cache = null, array $providers = array())
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($cache = null, array $providers = array())
{
// prepend the default provider to let users override it easily
array_unshift($providers, new ExpressionLanguageProvider());
diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
index 9b8105012c3d8..373369d455959 100644
--- a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
@@ -13,6 +13,9 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager;
+use Symfony\Component\Security\Core\AuthenticationEvents;
+use Symfony\Component\Security\Core\Event\AuthenticationEvent;
+use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
@@ -124,6 +127,50 @@ public function testEraseCredentialFlag()
$this->assertEquals('bar', $token->getCredentials());
}
+ public function testAuthenticateDispatchesAuthenticationFailureEvent()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+ $provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock();
+ $provider->expects($this->once())->method('supports')->willReturn(true);
+ $provider->expects($this->once())->method('authenticate')->willThrowException($exception = new AuthenticationException());
+
+ $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
+ $dispatcher
+ ->expects($this->once())
+ ->method('dispatch')
+ ->with(AuthenticationEvents::AUTHENTICATION_FAILURE, $this->equalTo(new AuthenticationFailureEvent($token, $exception)));
+
+ $manager = new AuthenticationProviderManager(array($provider));
+ $manager->setEventDispatcher($dispatcher);
+
+ try {
+ $manager->authenticate($token);
+ $this->fail('->authenticate() should rethrow exceptions');
+ } catch (AuthenticationException $e) {
+ $this->assertSame($token, $exception->getToken());
+ }
+ }
+
+ public function testAuthenticateDispatchesAuthenticationSuccessEvent()
+ {
+ $token = new UsernamePasswordToken('foo', 'bar', 'key');
+
+ $provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock();
+ $provider->expects($this->once())->method('supports')->willReturn(true);
+ $provider->expects($this->once())->method('authenticate')->willReturn($token);
+
+ $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
+ $dispatcher
+ ->expects($this->once())
+ ->method('dispatch')
+ ->with(AuthenticationEvents::AUTHENTICATION_SUCCESS, $this->equalTo(new AuthenticationEvent($token)));
+
+ $manager = new AuthenticationProviderManager(array($provider));
+ $manager->setEventDispatcher($dispatcher);
+
+ $this->assertSame($token, $manager->authenticate($token));
+ }
+
protected function getAuthenticationProvider($supports, $token = null, $exception = null)
{
$provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock();
diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
index 7ebe65c647d99..942a4a6350f27 100644
--- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php
@@ -90,6 +90,29 @@ public function testPasswordIsNotValid()
->assertRaised();
}
+ /**
+ * @dataProvider emptyPasswordData
+ */
+ public function testEmptyPasswordsAreNotValid($password)
+ {
+ $constraint = new UserPassword(array(
+ 'message' => 'myMessage',
+ ));
+
+ $this->validator->validate($password, $constraint);
+
+ $this->buildViolation('myMessage')
+ ->assertRaised();
+ }
+
+ public function emptyPasswordData()
+ {
+ return array(
+ array(null),
+ array(''),
+ );
+ }
+
/**
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
*/
diff --git a/src/Symfony/Component/Security/Core/User/UserProviderInterface.php b/src/Symfony/Component/Security/Core/User/UserProviderInterface.php
index 146ed65ad303d..9570edc2776ab 100644
--- a/src/Symfony/Component/Security/Core/User/UserProviderInterface.php
+++ b/src/Symfony/Component/Security/Core/User/UserProviderInterface.php
@@ -48,7 +48,7 @@ interface UserProviderInterface
public function loadUserByUsername($username);
/**
- * Refreshes the user for the account interface.
+ * Refreshes the user.
*
* It is up to the implementation to decide if the user data should be
* totally reloaded (e.g. from the database), or if the UserInterface
@@ -59,7 +59,7 @@ public function loadUserByUsername($username);
*
* @return UserInterface
*
- * @throws UnsupportedUserException if the account is not supported
+ * @throws UnsupportedUserException if the user is not supported
*/
public function refreshUser(UserInterface $user);
diff --git a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
index 5f4c146cab469..c2ab13b2f6d29 100644
--- a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
+++ b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
@@ -40,6 +40,8 @@ public function validate($password, Constraint $constraint)
}
if (null === $password || '' === $password) {
+ $this->context->addViolation($constraint->message);
+
return;
}
diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
index 2b3433c567d4a..188b79ade85ff 100644
--- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php
@@ -13,7 +13,6 @@
use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
-use Symfony\Component\Serializer\Exception\CircularReferenceException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
@@ -52,8 +51,6 @@ public function supportsNormalization($data, $format = null)
/**
* {@inheritdoc}
- *
- * @throws CircularReferenceException
*/
public function normalize($object, $format = null, array $context = array())
{
diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php
index 7d3d87c510c55..9217d51a95908 100644
--- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php
@@ -31,8 +31,6 @@ class ArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterfa
/**
* {@inheritdoc}
- *
- * @throws UnexpectedValueException
*/
public function denormalize($data, $class, $format = null, array $context = array())
{
diff --git a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php
index 988a491b7c800..9e5af130d03b7 100644
--- a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php
@@ -79,9 +79,6 @@ public function supportsNormalization($data, $format = null)
* Regex adapted from Brian Grinstead code.
*
* @see https://gist.github.com/bgrins/6194623
- *
- * @throws InvalidArgumentException
- * @throws UnexpectedValueException
*/
public function denormalize($data, $class, $format = null, array $context = array())
{
diff --git a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php
index 23df4829a8cbd..2b3b206287373 100644
--- a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php
+++ b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php
@@ -11,6 +11,13 @@
namespace Symfony\Component\Serializer\Normalizer;
+use Symfony\Component\Serializer\Exception\BadMethodCallException;
+use Symfony\Component\Serializer\Exception\ExtraAttributesException;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+use Symfony\Component\Serializer\Exception\LogicException;
+use Symfony\Component\Serializer\Exception\RuntimeException;
+use Symfony\Component\Serializer\Exception\UnexpectedValueException;
+
/**
* Defines the interface of denormalizers.
*
@@ -27,6 +34,13 @@ interface DenormalizerInterface
* @param array $context options available to the denormalizer
*
* @return object
+ *
+ * @throws BadMethodCallException Occurs when the normalizer is not called in an expected context
+ * @throws InvalidArgumentException Occurs when the arguments are not coherent or not supported
+ * @throws UnexpectedValueException Occurs when the item cannot be hydrated with the given data
+ * @throws ExtraAttributesException Occurs when the item doesn't have attribute to receive given data
+ * @throws LogicException Occurs when the normalizer is not supposed to denormalize
+ * @throws RuntimeException Occurs if the class cannot be instantiated
*/
public function denormalize($data, $class, $format = null, array $context = array());
diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php
index f7007840da1f4..2779053f741e9 100644
--- a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php
+++ b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php
@@ -11,6 +11,10 @@
namespace Symfony\Component\Serializer\Normalizer;
+use Symfony\Component\Serializer\Exception\CircularReferenceException;
+use Symfony\Component\Serializer\Exception\InvalidArgumentException;
+use Symfony\Component\Serializer\Exception\LogicException;
+
/**
* Defines the interface of normalizers.
*
@@ -26,6 +30,11 @@ interface NormalizerInterface
* @param array $context Context options for the normalizer
*
* @return array|scalar
+ *
+ * @throws InvalidArgumentException Occurs when the object given is not an attempted type for the normalizer
+ * @throws CircularReferenceException Occurs when the normalizer detects a circular reference when no circular
+ * reference handler can fix it
+ * @throws LogicException Occurs when the normalizer is not called in an expected context
*/
public function normalize($object, $format = null, array $context = array());