diff --git a/CHANGELOG-3.2.md b/CHANGELOG-3.2.md
index 5542e4160d1c3..de3c3fd9977b5 100644
--- a/CHANGELOG-3.2.md
+++ b/CHANGELOG-3.2.md
@@ -7,6 +7,11 @@ 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.11 (2017-07-05)
+
+ * bug #23390 [Cache] Handle APCu failures gracefully (nicolas-grekas)
+ * bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed)
+
* 3.2.10 (2017-07-04)
* bug #23366 [FrameworkBundle] Don't get() private services from debug:router (chalasr)
diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md
index b6113a82ad279..01e370cdefd0b 100644
--- a/CHANGELOG-3.3.md
+++ b/CHANGELOG-3.3.md
@@ -7,6 +7,32 @@ in 3.3 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.3.0...v3.3.1
+* 3.3.5 (2017-07-17)
+
+ * bug #23549 [PropertyInfo] conflict for phpdocumentor/reflection-docblock 3.2 (xabbuh)
+ * bug #23513 [FrameworkBundle] Set default public directory on install assets (yceruto)
+ * security #23507 [Security] validate empty passwords again (xabbuh)
+ * bug #23526 [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content (jnvsor)
+ * bug #23535 Make server:* commands work out of the box with the public/ root dir (fabpot)
+ * bug #23540 Disable inlining deprecated services (alekitto)
+ * bug #23498 [Process] Fixed issue between process builder and exec (lyrixx)
+ * bug #23490 [DependencyInjection] non-conflicting anonymous service ids across files (xabbuh)
+ * bug #23468 [DI] Handle root namespace in service definitions (ro0NL)
+ * bug #23477 [Process] Fix parsing args on Windows (nicolas-grekas)
+ * 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 #23465 [HttpKernel][VarDumper] Truncate profiler data & optim perf (nicolas-grekas)
+ * bug #23457 [FrameworkBundle] check _controller attribute is a string before parsing it (alekitto)
+ * 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 #23434 [DotEnv] Fix variable substitution (brieucthomas)
+ * bug #23426 Fixed HttpOnly flag when using Cookie::fromString() (Toflar)
+ * bug #22439 [DX] [TwigBundle] Enhance the new exception page design (sustmi)
+ * 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.3.4 (2017-07-05)
* bug #23413 [VarDumper] Reduce size of serialized Data objects (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/UPGRADE-4.0.md b/UPGRADE-4.0.md
index b06145202e7cd..17818f7368ca4 100644
--- a/UPGRADE-4.0.md
+++ b/UPGRADE-4.0.md
@@ -402,7 +402,7 @@ HttpKernel
Ldap
----
- * The `RenameEntryInterface` has been deprecated, and merged with `EntryManagerInterface`
+ * The `RenameEntryInterface` has been removed, and merged with `EntryManagerInterface`
Process
-------
@@ -443,7 +443,7 @@ SecurityBundle
* The `UserPasswordEncoderCommand` class does not allow `null` as the first argument anymore.
- * `UserPasswordEncoderCommand` does not implement `ContainerAwareInterface` anymore.
+ * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` nor implement `ContainerAwareInterface` anymore.
Serializer
----------
diff --git a/composer.json b/composer.json
index 3b096baff3c55..cf55aeb8ef072 100644
--- a/composer.json
+++ b/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": ">=5.5.9",
+ "ext-xml": "*",
"doctrine/common": "~2.4",
"fig/link-util": "^1.0",
"twig/twig": "~1.34|~2.4",
@@ -101,7 +102,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 7bf23af8d6ada..77e2d1c5621ba 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 b760d28997611..ba704e00f2a7a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -71,7 +71,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/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
index 38256791ff565..3e2222f813ec7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
@@ -46,16 +46,16 @@ protected function configure()
$this
->setName('assets:install')
->setDefinition(array(
- new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', 'web'),
+ new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', 'public'),
))
->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlinks the assets instead of copying it')
->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks')
- ->setDescription('Installs bundles web assets under a public web directory')
+ ->setDescription('Installs bundles web assets under a public directory')
->setHelp(<<<'EOT'
The %command.name% command installs bundle assets into a given
-directory (e.g. the web directory).
+directory (e.g. the public directory).
- php %command.full_name% web
+ php %command.full_name% public
A "bundles" directory will be created inside the target directory and the
"Resources/public" directory of each bundle will be copied into it.
@@ -63,11 +63,11 @@ protected function configure()
To create a symlink to each bundle instead of copying its assets, use the
--symlink option (will fall back to hard copies when symbolic links aren't possible:
- php %command.full_name% web --symlink
+ php %command.full_name% public --symlink
To make symlink relative, add the --relative option:
- php %command.full_name% web --symlink --relative
+ php %command.full_name% public --symlink --relative
EOT
)
@@ -85,7 +85,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
$targetArg = $this->getContainer()->getParameter('kernel.project_dir').'/'.$targetArg;
if (!is_dir($targetArg)) {
- throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
+ // deprecated, logic to be removed in 4.0
+ // this allows the commands to work out of the box with web/ and public/
+ if (is_dir(dirname($targetArg).'/web')) {
+ $targetArg = dirname($targetArg).'/web';
+ } else {
+ throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
+ }
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
index e4a86dc6ef249..967c6133f43f7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
@@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Component\Cache\Adapter\AbstractAdapter;
+use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -72,7 +73,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/EventListener/ResolveControllerNameSubscriber.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php
index b083bb7ba8723..6072061dbac04 100644
--- a/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php
+++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php
@@ -33,7 +33,7 @@ public function __construct(ControllerNameParser $parser)
public function onKernelRequest(GetResponseEvent $event)
{
$controller = $event->getRequest()->attributes->get('_controller');
- if ($controller && false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
+ if (is_string($controller) && false === strpos($controller, '::') && 2 === substr_count($controller, ':')) {
// controller in the a:b:c notation then
$event->getRequest()->attributes->set('_controller', $this->parser->parse($controller));
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php
index 713cd4eaca842..4619301b6e997 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\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
@@ -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 ChildDefinition('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/EventListener/ResolveControllerNameSubscriberTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php
index e5cc6d28a4e9d..338c1ec81a5c0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php
@@ -37,7 +37,10 @@ public function testReplacesControllerAttribute()
$this->assertEquals('App\\Final\\Format::methodName', $request->attributes->get('_controller'));
}
- public function testSkipsOtherControllerFormats()
+ /**
+ * @dataProvider provideSkippedControllers
+ */
+ public function testSkipsOtherControllerFormats($controller)
{
$parser = $this->getMockBuilder(ControllerNameParser::class)->disableOriginalConstructor()->getMock();
$parser->expects($this->never())
@@ -45,10 +48,16 @@ public function testSkipsOtherControllerFormats()
$httpKernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
$request = new Request();
- $request->attributes->set('_controller', 'Other:format');
+ $request->attributes->set('_controller', $controller);
$subscriber = new ResolveControllerNameSubscriber($parser);
$subscriber->onKernelRequest(new GetResponseEvent($httpKernel, $request, HttpKernelInterface::MASTER_REQUEST));
- $this->assertEquals('Other:format', $request->attributes->get('_controller'));
+ $this->assertEquals($controller, $request->attributes->get('_controller'));
+ }
+
+ public function provideSkippedControllers()
+ {
+ yield array('Other:format');
+ yield array(function () {});
}
}
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/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index 6db169024f67e..1105daa373f43 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -80,7 +80,6 @@
"symfony/validator": "For using validation",
"symfony/yaml": "For using the debug:config and lint:yaml commands",
"symfony/property-info": "For using the property_info service",
- "symfony/process": "For using the server:run, server:start, server:stop, and server:status commands",
"symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering"
},
"autoload": {
diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
index 4185d409fb445..238830fd85179 100644
--- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
@@ -7,7 +7,7 @@ CHANGELOG
* Deprecated instantiating `UserPasswordEncoderCommand` without its constructor
arguments fully provided.
* Deprecated `UserPasswordEncoderCommand::getContainer()` and relying on the
- `ContainerAwareInterface` interface for this command.
+ `ContainerAwareCommand` sub class or `ContainerAwareInterface` implementation for this command.
* Deprecated the `FirewallMap::$map` and `$container` properties.
* [BC BREAK] Keys of the `users` node for `in_memory` user provider are no longer normalized.
* deprecated `FirewallContext::getListeners()`
diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
index a588bdd331e96..6c3f0327491c4 100644
--- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
+++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php
@@ -51,7 +51,7 @@ public function __construct(EncoderFactoryInterface $encoderFactory = null, arra
*/
protected function getContainer()
{
- @trigger_error(sprintf('Method "%s" is deprecated since version 3.3 and "%s" won\'t implement "%s" anymore in 4.0.', __METHOD__, __CLASS__, ContainerAwareInterface::class), E_USER_DEPRECATED);
+ @trigger_error(sprintf('Method "%s" is deprecated since version 3.3 and "%s" won\'t extend "%s" nor implement "%s" anymore in 4.0.', __METHOD__, __CLASS__, ContainerAwareCommand::class, ContainerAwareInterface::class), E_USER_DEPRECATED);
return parent::getContainer();
}
diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json
index d0cd5fc6c953d..2c9a641e503d7 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.3",
"symfony/dependency-injection": "~3.3",
"symfony/http-kernel": "~3.3",
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/Resources/views/Exception/trace.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig
index a6af5d0532242..1d8125a38f84b 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig
@@ -1,28 +1,29 @@
-{% if trace.file|default(false) %}
- {{ include('@Twig/images/icon-minus-square.svg') }}
- {{ include('@Twig/images/icon-plus-square.svg') }}
-{% endif %}
-
-{% if trace.function %}
- {{ trace.class|abbr_class }}{% if trace.type is not empty %}{{ trace.type }}{% endif %}{{ trace.function }}({{ trace.args|format_args }})
-{% endif %}
+
{% if trace.file|default(false) %}
- {{ trace.file|file_excerpt(trace.line)|replace({
+ {{ trace.file|file_excerpt(trace.line, 5)|replace({
'#DD0000': '#183691',
'#007700': '#a71d5d',
'#0000BB': '#222222',
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig
index 948ee86fa6cc5..2bf3e7613aad4 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig
@@ -1,37 +1,33 @@
-
-
-
-
-
-
- {{ exception.class|split('\\')|slice(0, -1)|join('\\') }}
- {{- exception.class|split('\\')|length > 1 ? '\\' }}
-
- {{ exception.class|split('\\')|last }}
+
+
+
+
+
+ {{ exception.class|split('\\')|slice(0, -1)|join('\\') }}
+ {{- exception.class|split('\\')|length > 1 ? '\\' }}
+
+ {{ exception.class|split('\\')|last }}
- {{ include('@Twig/images/icon-minus-square-o.svg') }}
- {{ include('@Twig/images/icon-plus-square-o.svg') }}
-
+ {{ include('@Twig/images/icon-minus-square-o.svg') }}
+ {{ include('@Twig/images/icon-plus-square-o.svg') }}
+
- {% if exception.message is not empty and index > 1 %}
- {{ exception.message }}
- {% endif %}
- |
-
-
+ {% if exception.message is not empty and index > 1 %}
+ {{ exception.message }}
+ {% endif %}
+
+
-
+
{% set _is_first_user_code = true %}
{% for i, trace in exception.trace %}
{% set _display_code_snippet = _is_first_user_code and ('/vendor/' not in trace.file) and ('/var/cache/' not in trace.file) and (trace.file is not empty) %}
{% if _display_code_snippet %}{% set _is_first_user_code = false %}{% endif %}
-
-
- {{ include('@Twig/Exception/trace.html.twig', { prefix: index, i: i, trace: trace }, with_context = false) }}
- |
-
+
+ {{ include('@Twig/Exception/trace.html.twig', { prefix: index, i: i, trace: trace, _display_code_snippet: _display_code_snippet }, with_context = false) }}
+
{% endfor %}
-
-
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig
index cb455274eecf9..ba3dd9412e266 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig
@@ -89,30 +89,34 @@ header .container { display: flex; justify-content: space-between; }
.exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; }
.trace + .trace { margin-top: 30px; }
+.trace-head { background-color: #e0e0e0; padding: 10px; }
.trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; }
.trace-head .trace-namespace { color: #999; display: block; font-size: 13px; }
.trace-head .icon { position: absolute; right: 0; top: 0; }
.trace-head .icon svg { height: 24px; width: 24px; }
+.trace-details { background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; }
+
.trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; }
.trace-details { table-layout: fixed; }
-.trace-line { position: relative; padding-left: 36px; }
-.trace-line.sf-toggle:hover { background: #F5F5F5; }
+.trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; }
+.trace-line:hover { background: #F5F5F5; }
.trace-line a { color: #222; }
.trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; }
.trace-line .icon svg { height: 16px; width: 16px; }
+.trace-line-header { padding-left: 36px; }
-.trace-file-path, .trace-file-path a { margin-top: 3px; color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; }
+.trace-file-path, .trace-file-path a { color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; }
.trace-class { color: #B0413E; }
.trace-type { padding: 0 2px; }
.trace-method { color: #B0413E; color: #222; font-weight: bold; color: #B0413E; }
.trace-arguments { color: #222; color: #999; font-weight: normal; color: #795da3; color: #777; padding-left: 2px; }
-.trace-code { background: #FFF; font-size: 12px; margin: 10px 0 2px; padding: 10px; overflow-x: auto; }
+.trace-code { background: #FFF; font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; }
.trace-code ol { margin: 0; float: left; }
.trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; }
.trace-code li + li { margin-top: 5px; }
-.trace-code li.selected { background: #F8EEC7; padding: 3px 0 3px 10px; margin-top: 2px; }
+.trace-code li.selected { background: #F7E5A1; margin-top: 2px; }
.trace-code li code { color: #222; white-space: nowrap; }
.trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; }
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 2de7fd10a461c..e38bf5390617e 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 423e1c66a293a..9f3ced558e82c 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig
@@ -563,3 +563,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/Bundle/WebServerBundle/Command/ServerRunCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php
index 53ce350e7fae2..4c228ad93bee0 100644
--- a/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php
+++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php
@@ -88,6 +88,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output);
+ // deprecated, logic to be removed in 4.0
+ // this allows the commands to work out of the box with web/ and public/
+ if ($this->documentRoot && !is_dir($this->documentRoot) && is_dir(dirname($this->documentRoot).'/web')) {
+ $this->documentRoot = dirname($this->documentRoot).'/web';
+ }
+
if (null === $documentRoot = $input->getOption('docroot')) {
if (!$this->documentRoot) {
$io->error('The document root directory must be either passed as first argument of the constructor or through the "--docroot" input option.');
@@ -97,12 +103,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
$documentRoot = $this->documentRoot;
}
- if (!is_dir($documentRoot)) {
- $io->error(sprintf('The document root directory "%s" does not exist.', $documentRoot));
-
- return 1;
- }
-
if (!$env = $this->environment) {
if ($input->hasOption('env') && !$env = $input->getOption('env')) {
$io->error('The environment must be either passed as second argument of the constructor or through the "--env" input option.');
diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php
index 7cf83ab54e14e..57de788608547 100644
--- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php
+++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php
@@ -100,6 +100,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
return 1;
}
+ // deprecated, logic to be removed in 4.0
+ // this allows the commands to work out of the box with web/ and public/
+ if ($this->documentRoot && !is_dir($this->documentRoot) && is_dir(dirname($this->documentRoot).'/web')) {
+ $this->documentRoot = dirname($this->documentRoot).'/web';
+ }
+
if (null === $documentRoot = $input->getOption('docroot')) {
if (!$this->documentRoot) {
$io->error('The document root directory must be either passed as first argument of the constructor or through the "docroot" input option.');
@@ -109,12 +115,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
$documentRoot = $this->documentRoot;
}
- if (!is_dir($documentRoot)) {
- $io->error(sprintf('The document root directory "%s" does not exist.', $documentRoot));
-
- return 1;
- }
-
if (!$env = $this->environment) {
if ($input->hasOption('env') && !$env = $input->getOption('env')) {
$io->error('The environment must be either passed as second argument of the constructor or through the "--env" input option.');
diff --git a/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml b/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml
index 2815c6d2cfbf5..1723e0bcd925f 100644
--- a/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml
+++ b/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml
@@ -8,13 +8,13 @@
- %kernel.project_dir%/web
+ %kernel.project_dir%/public
%kernel.environment%
- %kernel.project_dir%/web
+ %kernel.project_dir%/public
%kernel.environment%
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 3ae553c705a3e..26b33e683e2ff 100644
--- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
@@ -32,6 +32,10 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface
private $createCacheItem;
private $mergeByLifetime;
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ */
protected function __construct($namespace = '', $defaultLifetime = 0)
{
$this->namespace = '' === $namespace ? '' : $this->getId($namespace).':';
@@ -74,6 +78,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) {
diff --git a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
index 713e9fd7d8e88..50554ed688309 100644
--- a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php
@@ -17,6 +17,13 @@ class ApcuAdapter extends AbstractAdapter
{
use ApcuTrait;
+ /**
+ * @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)
{
$this->init($namespace, $defaultLifetime, $version);
diff --git a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php
index befff7ca8ec7b..972d2b41545ef 100644
--- a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php
@@ -18,6 +18,11 @@ class DoctrineAdapter extends AbstractAdapter
{
use DoctrineTrait;
+ /**
+ * @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 f37cde290f92c..a6bb335bbdc3f 100644
--- a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php
@@ -17,6 +17,11 @@ class FilesystemAdapter extends AbstractAdapter
{
use FilesystemTrait;
+ /**
+ * @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 12480c7436f0f..fee500dbfc7e2 100644
--- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php
+++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php
@@ -18,6 +18,13 @@ class PhpFilesAdapter extends AbstractAdapter
{
use PhpFilesTrait;
+ /**
+ * @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/Simple/AbstractCache.php b/src/Symfony/Component/Cache/Simple/AbstractCache.php
index bbd35780fd5c4..e4046463f1609 100644
--- a/src/Symfony/Component/Cache/Simple/AbstractCache.php
+++ b/src/Symfony/Component/Cache/Simple/AbstractCache.php
@@ -30,6 +30,10 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface
private $defaultLifetime;
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ */
protected function __construct($namespace = '', $defaultLifetime = 0)
{
$this->defaultLifetime = max(0, (int) $defaultLifetime);
diff --git a/src/Symfony/Component/Cache/Simple/ApcuCache.php b/src/Symfony/Component/Cache/Simple/ApcuCache.php
index 16aa8661f07a2..e583b44341dce 100644
--- a/src/Symfony/Component/Cache/Simple/ApcuCache.php
+++ b/src/Symfony/Component/Cache/Simple/ApcuCache.php
@@ -17,6 +17,11 @@ class ApcuCache extends AbstractCache
{
use ApcuTrait;
+ /**
+ * @param string $namespace
+ * @param int $defaultLifetime
+ * @param string|null $version
+ */
public function __construct($namespace = '', $defaultLifetime = 0, $version = null)
{
$this->init($namespace, $defaultLifetime, $version);
diff --git a/src/Symfony/Component/Cache/Simple/DoctrineCache.php b/src/Symfony/Component/Cache/Simple/DoctrineCache.php
index 395c34dd81bd0..00f0b9c6fc326 100644
--- a/src/Symfony/Component/Cache/Simple/DoctrineCache.php
+++ b/src/Symfony/Component/Cache/Simple/DoctrineCache.php
@@ -18,6 +18,11 @@ class DoctrineCache extends AbstractCache
{
use DoctrineTrait;
+ /**
+ * @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/Simple/FilesystemCache.php b/src/Symfony/Component/Cache/Simple/FilesystemCache.php
index a60312ea57fed..dac9ade9ca40e 100644
--- a/src/Symfony/Component/Cache/Simple/FilesystemCache.php
+++ b/src/Symfony/Component/Cache/Simple/FilesystemCache.php
@@ -17,6 +17,11 @@ class FilesystemCache extends AbstractCache
{
use FilesystemTrait;
+ /**
+ * @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/Simple/MemcachedCache.php b/src/Symfony/Component/Cache/Simple/MemcachedCache.php
index 1d5ee73c31d2c..7717740622c5e 100644
--- a/src/Symfony/Component/Cache/Simple/MemcachedCache.php
+++ b/src/Symfony/Component/Cache/Simple/MemcachedCache.php
@@ -19,6 +19,11 @@ class MemcachedCache extends AbstractCache
protected $maxIdLength = 250;
+ /**
+ * @param \Memcached $client
+ * @param string $namespace
+ * @param int $defaultLifetime
+ */
public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0)
{
$this->init($client, $namespace, $defaultLifetime);
diff --git a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php
index c4d120080637b..810b80f81275c 100644
--- a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php
+++ b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php
@@ -18,6 +18,13 @@ class PhpFilesCache extends AbstractCache
{
use PhpFilesTrait;
+ /**
+ * @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/Simple/RedisCache.php b/src/Symfony/Component/Cache/Simple/RedisCache.php
index 799a3d082fede..e82c0627e241d 100644
--- a/src/Symfony/Component/Cache/Simple/RedisCache.php
+++ b/src/Symfony/Component/Cache/Simple/RedisCache.php
@@ -19,6 +19,8 @@ class RedisCache extends AbstractCache
/**
* @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient
+ * @param string $namespace
+ * @param int $defaultLifetime
*/
public function __construct($redisClient, $namespace = '', $defaultLifetime = 0)
{
diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php
index 7ebc36f0a5814..6cad6135cf4a0 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 7a5da70d09567..f2ef363c837cc 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
@@ -82,7 +82,7 @@ private function isInlineableDefinition($id, Definition $definition, ServiceRefe
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 fdb780f014d3a..96bf8ee36f274 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 6c2f1bf6e84fb..02c17150b4e34 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -120,7 +120,6 @@ public function dump(array $options = array())
'debug' => true,
), $options);
- $this->classResources = array();
$this->initializeMethodNamesMap($options['base_class']);
$this->docStar = $options['debug'] ? '*' : '';
@@ -397,15 +396,9 @@ private function addServiceReturn($id, $isSimpleInstance)
*/
private function addServiceInstance($id, Definition $definition, $isSimpleInstance)
{
- $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));
}
@@ -1564,11 +1557,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/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
index 7a0123ba21bf5..8e751be1027c2 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
@@ -121,11 +121,11 @@ public function load($resource, $type = null)
// parameters
if (isset($content['parameters'])) {
if (!is_array($content['parameters'])) {
- throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $resource));
+ throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $path));
}
foreach ($content['parameters'] as $key => $value) {
- $this->container->setParameter($key, $this->resolveServices($value, $resource, true));
+ $this->container->setParameter($key, $this->resolveServices($value, $path, true));
}
}
@@ -136,7 +136,7 @@ public function load($resource, $type = null)
$this->anonymousServicesCount = 0;
$this->setCurrentDir(dirname($path));
try {
- $this->parseDefinitions($content, $resource);
+ $this->parseDefinitions($content, $path);
} finally {
$this->instanceof = array();
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
index 51f7001491a19..51397309b7dce 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
@@ -1082,6 +1082,27 @@ public function testRegisterForAutoconfiguration()
// when called multiple times, the same instance is returned
$this->assertSame($childDefA, $container->registerForAutoconfiguration('AInterface'));
}
+
+ /**
+ * 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 1c1e91a9eb046..e2478ea22b3b4 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
@@ -165,8 +165,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 bd8a95bab91eb..6eec6428c2cc4 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
@@ -584,4 +584,44 @@ 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');
+ $container->compile();
+
+ $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/DependencyInjection/Tests/Fixtures/yaml/bar/services.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bar/services.yml
new file mode 100644
index 0000000000000..0f846f5f76c6e
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bar/services.yml
@@ -0,0 +1,4 @@
+services:
+ AppBundle\Foo:
+ arguments:
+ - !service {class: AppBundle\Bar }
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/foo/services.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/foo/services.yml
new file mode 100644
index 0000000000000..76eee552fac22
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/foo/services.yml
@@ -0,0 +1,4 @@
+services:
+ AppBundle\Hello:
+ arguments:
+ - !service {class: AppBundle\World}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
index 2c655d718998f..b8ac2fc0e9296 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
@@ -501,7 +501,7 @@ public function testDecoratedServicesWithWrongSyntaxThrowsException()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
- * @expectedExceptionMessage Parameter "tags" must be an array for service "Foo\Bar" in services31_invalid_tags.yml. Check your YAML syntax.
+ * @expectedExceptionMessageRegExp /Parameter "tags" must be an array for service "Foo\\Bar" in .+services31_invalid_tags\.yml\. Check your YAML syntax./
*/
public function testInvalidTagsWithDefaults()
{
@@ -534,7 +534,7 @@ public function testAnonymousServices()
$this->assertCount(1, $args);
$this->assertInstanceOf(Reference::class, $args[0]);
$this->assertTrue($container->has((string) $args[0]));
- $this->assertStringStartsWith('2', (string) $args[0]);
+ $this->assertRegExp('/^\d+_[A-Za-z0-9]{64}$/', (string) $args[0]);
$anonymous = $container->getDefinition((string) $args[0]);
$this->assertEquals('Bar', $anonymous->getClass());
@@ -546,7 +546,7 @@ public function testAnonymousServices()
$this->assertInternalType('array', $factory);
$this->assertInstanceOf(Reference::class, $factory[0]);
$this->assertTrue($container->has((string) $factory[0]));
- $this->assertStringStartsWith('1', (string) $factory[0]);
+ $this->assertRegExp('/^\d+_[A-Za-z0-9]{64}$/', (string) $factory[0]);
$this->assertEquals('constructFoo', $factory[1]);
$anonymous = $container->getDefinition((string) $factory[0]);
@@ -555,6 +555,19 @@ public function testAnonymousServices()
$this->assertFalse($anonymous->isAutowired());
}
+ public function testAnonymousServicesInDifferentFilesWithSameNameDoNotConflict()
+ {
+ $container = new ContainerBuilder();
+
+ $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/foo'));
+ $loader->load('services.yml');
+
+ $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/bar'));
+ $loader->load('services.yml');
+
+ $this->assertCount(5, $container->getDefinitions());
+ }
+
public function testAnonymousServicesInInstanceof()
{
$container = new ContainerBuilder();
@@ -582,7 +595,7 @@ public function testAnonymousServicesInInstanceof()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
- * @expectedExceptionMessage Creating an alias using the tag "!service" is not allowed in "anonymous_services_alias.yml".
+ * @expectedExceptionMessageRegExp /Creating an alias using the tag "!service" is not allowed in ".+anonymous_services_alias\.yml"\./
*/
public function testAnonymousServicesWithAliases()
{
@@ -593,7 +606,7 @@ public function testAnonymousServicesWithAliases()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
- * @expectedExceptionMessage Using an anonymous service in a parameter is not allowed in "anonymous_services_in_parameters.yml".
+ * @expectedExceptionMessageRegExp /Using an anonymous service in a parameter is not allowed in ".+anonymous_services_in_parameters\.yml"\./
*/
public function testAnonymousServicesInParameters()
{
@@ -614,7 +627,7 @@ public function testAutoConfigureInstanceof()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
- * @expectedExceptionMessage Service "_defaults" key must be an array, "NULL" given in "bad_empty_defaults.yml".
+ * @expectedExceptionMessageRegExp /Service "_defaults" key must be an array, "NULL" given in ".+bad_empty_defaults\.yml"\./
*/
public function testEmptyDefaultsThrowsClearException()
{
@@ -625,7 +638,7 @@ public function testEmptyDefaultsThrowsClearException()
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
- * @expectedExceptionMessage Service "_instanceof" key must be an array, "NULL" given in "bad_empty_instanceof.yml".
+ * @expectedExceptionMessageRegExp /Service "_instanceof" key must be an array, "NULL" given in ".+bad_empty_instanceof\.yml"\./
*/
public function testEmptyInstanceofThrowsClearException()
{
diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php
index 00f27bb7b3cdd..2e907b8c980b8 100644
--- a/src/Symfony/Component/Dotenv/Dotenv.php
+++ b/src/Symfony/Component/Dotenv/Dotenv.php
@@ -351,7 +351,7 @@ private function resolveVariables($value)
}
$name = $matches[3];
- $value = isset($this->values[$name]) ? $this->values[$name] : (isset($_ENV[$name]) ? isset($_ENV[$name]) : (string) getenv($name));
+ $value = isset($this->values[$name]) ? $this->values[$name] : (isset($_ENV[$name]) ? $_ENV[$name] : (string) getenv($name));
if (!$matches[2] && isset($matches[4])) {
$value .= '}';
diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php
index a7f211ecd6e37..47598030a87f1 100644
--- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php
+++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php
@@ -63,6 +63,7 @@ public function testParse($data, $expected)
public function getEnvData()
{
putenv('LOCAL=local');
+ $_ENV['REMOTE'] = 'remote';
$tests = array(
// spaces
@@ -134,6 +135,7 @@ public function getEnvData()
array('FOO=" \\$ "', array('FOO' => ' $ ')),
array('FOO=" $ "', array('FOO' => ' $ ')),
array('BAR=$LOCAL', array('BAR' => 'local')),
+ array('BAR=$REMOTE', array('BAR' => 'remote')),
array('FOO=$NOTDEFINED', array('FOO' => '')),
);
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index 320eb151166aa..9c440fc745308 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/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php
index b088abc7962f6..378edf563b972 100644
--- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php
+++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php
@@ -16,15 +16,10 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
-use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\VarDumper\Caster\Caster;
use Symfony\Component\VarDumper\Caster\ClassStub;
-use Symfony\Component\VarDumper\Caster\CutStub;
-use Symfony\Component\VarDumper\Cloner\ClonerInterface;
-use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\VarDumper\Cloner\Stub;
-use Symfony\Component\VarDumper\Cloner\VarCloner;
/**
* Data collector for {@link FormInterface} instances.
@@ -72,16 +67,6 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf
*/
private $formsByView;
- /**
- * @var ValueExporter
- */
- private $valueExporter;
-
- /**
- * @var ClonerInterface
- */
- private $cloner;
-
private $hasVarDumper;
public function __construct(FormDataExtractorInterface $dataExtractor)
@@ -255,61 +240,33 @@ public function serialize()
/**
* {@inheritdoc}
*/
- protected function cloneVar($var, $isClass = false)
+ protected function getCasters()
{
- if ($var instanceof Data) {
- return $var;
- }
- if (null === $this->cloner) {
- if ($this->hasVarDumper) {
- $this->cloner = new VarCloner();
- $this->cloner->setMaxItems(-1);
- $this->cloner->addCasters(array(
- '*' => function ($v, array $a, Stub $s, $isNested) {
- foreach ($a as &$v) {
- if (is_object($v) && !$v instanceof \DateTimeInterface) {
- $v = new CutStub($v);
- }
- }
-
- return $a;
- },
- \Exception::class => function (\Exception $e, array $a, Stub $s) {
- if (isset($a[$k = "\0Exception\0previous"])) {
- unset($a[$k]);
- ++$s->cut;
- }
-
- return $a;
- },
- FormInterface::class => function (FormInterface $f, array $a) {
- return array(
- Caster::PREFIX_VIRTUAL.'name' => $f->getName(),
- Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())),
- );
- },
- ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) {
- return array(
- Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(),
- Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(),
- Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(),
- );
- },
- ));
- } else {
- @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED);
- $this->cloner = false;
- }
- }
- if (false !== $this->cloner) {
- return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE);
- }
-
- if (null === $this->valueExporter) {
- $this->valueExporter = new ValueExporter();
- }
+ return parent::getCasters() + array(
+ \Exception::class => function (\Exception $e, array $a, Stub $s) {
+ foreach (array("\0Exception\0previous", "\0Exception\0trace") as $k) {
+ if (isset($a[$k])) {
+ unset($a[$k]);
+ ++$s->cut;
+ }
+ }
- return $this->valueExporter->exportValue($var);
+ return $a;
+ },
+ FormInterface::class => function (FormInterface $f, array $a) {
+ return array(
+ Caster::PREFIX_VIRTUAL.'name' => $f->getName(),
+ Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())),
+ );
+ },
+ ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) {
+ return array(
+ Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(),
+ Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(),
+ Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(),
+ );
+ },
+ );
}
private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash)
diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json
index 5a1d6ef9cba51..85250b87f357b 100644
--- a/src/Symfony/Component/Form/composer.json
+++ b/src/Symfony/Component/Form/composer.json
@@ -29,7 +29,7 @@
"symfony/dependency-injection": "~3.3",
"symfony/config": "~2.7|~3.0",
"symfony/http-foundation": "~2.8|~3.0",
- "symfony/http-kernel": "~2.8|~3.0",
+ "symfony/http-kernel": "^3.3.5",
"symfony/security-csrf": "~2.8|~3.0",
"symfony/translation": "~2.8|~3.0",
"symfony/var-dumper": "~3.3"
@@ -39,8 +39,8 @@
"symfony/dependency-injection": "<3.3",
"symfony/doctrine-bridge": "<2.7",
"symfony/framework-bundle": "<2.7",
- "symfony/twig-bridge": "<2.7",
- "symfony/var-dumper": "<3.3"
+ "symfony/http-kernel": "<3.3.5",
+ "symfony/twig-bridge": "<2.7"
},
"suggest": {
"symfony/validator": "For form validation.",
diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php
index 2ac902685d329..4d709c0e91aa3 100644
--- a/src/Symfony/Component/HttpFoundation/Cookie.php
+++ b/src/Symfony/Component/HttpFoundation/Cookie.php
@@ -46,7 +46,7 @@ public static function fromString($cookie, $decode = false)
'path' => '/',
'domain' => null,
'secure' => false,
- 'httponly' => true,
+ 'httponly' => false,
'raw' => !$decode,
'samesite' => null,
);
@@ -145,7 +145,7 @@ public function __toString()
if ('' === (string) $this->getValue()) {
$str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-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()).'; max-age='.$this->getMaxAge();
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 edaed2533b1bd..56f871e7b6fff 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php
@@ -164,6 +164,9 @@ public function testToString()
$cookie = new Cookie('foo', 'bar', $expire = 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; max-age='.($expire - time()).'; 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; max-age='.($expire - time()).'; 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', $expire = time() - 31536001).'; max-age='.($expire - time()).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL');
@@ -175,7 +178,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());
@@ -200,6 +203,15 @@ public function testFromString()
$this->assertEquals(new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, true), $cookie);
$cookie = Cookie::fromString('foo=bar', true);
- $this->assertEquals(new Cookie('foo', 'bar'), $cookie);
+ $this->assertEquals(new Cookie('foo', 'bar', 0, '/', null, false, false), $cookie);
+ }
+
+ public function testFromStringWithHttpOnly()
+ {
+ $cookie = Cookie::fromString('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly');
+ $this->assertTrue($cookie->isHttpOnly());
+
+ $cookie = Cookie::fromString('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure');
+ $this->assertFalse($cookie->isHttpOnly());
}
}
diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php
index 724328ae850e4..41365672141aa 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php
@@ -241,12 +241,12 @@ public function testSetCookieHeader()
{
$bag = new ResponseHeaderBag();
$bag->set('set-cookie', 'foo=bar');
- $this->assertEquals(array(new Cookie('foo', 'bar', 0, '/', null, false, true, true)), $bag->getCookies());
+ $this->assertEquals(array(new Cookie('foo', 'bar', 0, '/', null, false, false, true)), $bag->getCookies());
$bag->set('set-cookie', 'foo2=bar2', false);
$this->assertEquals(array(
- new Cookie('foo', 'bar', 0, '/', null, false, true, true),
- new Cookie('foo2', 'bar2', 0, '/', null, false, true, true),
+ new Cookie('foo', 'bar', 0, '/', null, false, false, true),
+ new Cookie('foo2', 'bar2', 0, '/', null, false, false, true),
), $bag->getCookies());
$bag->remove('set-cookie');
diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php
index 0d574eae3b3af..845c2c1380b01 100644
--- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php
+++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php
@@ -12,9 +12,10 @@
namespace Symfony\Component\HttpKernel\DataCollector;
use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
-use Symfony\Component\VarDumper\Caster\ClassStub;
+use Symfony\Component\VarDumper\Caster\CutStub;
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Cloner\Stub;
use Symfony\Component\VarDumper\Cloner\VarCloner;
/**
@@ -37,7 +38,7 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable
/**
* @var ClonerInterface
*/
- private static $cloner;
+ private $cloner;
public function serialize()
{
@@ -61,16 +62,20 @@ public function unserialize($data)
*/
protected function cloneVar($var)
{
- if (null === self::$cloner) {
- if (class_exists(ClassStub::class)) {
- self::$cloner = new VarCloner();
- self::$cloner->setMaxItems(-1);
+ if ($var instanceof Data) {
+ return $var;
+ }
+ if (null === $this->cloner) {
+ if (class_exists(CutStub::class)) {
+ $this->cloner = new VarCloner();
+ $this->cloner->setMaxItems(-1);
+ $this->cloner->addCasters($this->getCasters());
} else {
@trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED);
- self::$cloner = false;
+ $this->cloner = false;
}
}
- if (false === self::$cloner) {
+ if (false === $this->cloner) {
if (null === $this->valueExporter) {
$this->valueExporter = new ValueExporter();
}
@@ -78,7 +83,7 @@ protected function cloneVar($var)
return $this->valueExporter->exportValue($var);
}
- return self::$cloner->cloneVar($var);
+ return $this->cloner->cloneVar($var);
}
/**
@@ -100,4 +105,24 @@ protected function varToString($var)
return $this->valueExporter->exportValue($var);
}
+
+ /**
+ * @return callable[] The casters to add to the cloner
+ */
+ protected function getCasters()
+ {
+ return array(
+ '*' => function ($v, array $a, Stub $s, $isNested) {
+ if (!$v instanceof Stub) {
+ foreach ($a as $k => $v) {
+ if (is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) {
+ $a[$k] = new CutStub($v);
+ }
+ }
+ }
+
+ return $a;
+ },
+ );
+ }
}
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index 0fc96a0acc71f..d73ad52a0e648 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -61,11 +61,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface
private $projectDir;
- const VERSION = '3.3.4';
- const VERSION_ID = 30304;
+ const VERSION = '3.3.5';
+ const VERSION_ID = 30305;
const MAJOR_VERSION = 3;
const MINOR_VERSION = 3;
- const RELEASE_VERSION = 4;
+ const RELEASE_VERSION = 5;
const EXTRA_VERSION = '';
const END_OF_MAINTENANCE = '01/2018';
diff --git a/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php b/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php
index 8bc70bda9637a..c15cb16e77e80 100644
--- a/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php
+++ b/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php
@@ -5,9 +5,9 @@
use Symfony\Component\Ldap\Entry;
/**
- * @deprecated This interface will be deprecated in 4.0, and merged with `EntryManagerInterface`
- *
* @author Kevin Schuurmans
+ *
+ * @deprecated since version 3.3, will be merged with {@link EntryManagerInterface} in 4.0.
*/
interface RenameEntryInterface
{
diff --git a/src/Symfony/Component/Ldap/CHANGELOG.md b/src/Symfony/Component/Ldap/CHANGELOG.md
index 61af4adf151a2..5d90f278f567a 100644
--- a/src/Symfony/Component/Ldap/CHANGELOG.md
+++ b/src/Symfony/Component/Ldap/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+3.3.0
+-----
+
+* The `RenameEntryInterface` inferface is deprecated, and will be merged with `EntryManagerInterface` in 4.0.
+
3.1.0
-----
diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php
index fb12d393abad7..05f88d2d1b112 100644
--- a/src/Symfony/Component/Process/Process.php
+++ b/src/Symfony/Component/Process/Process.php
@@ -1633,14 +1633,17 @@ private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env
$varCount = 0;
$varCache = array();
$cmd = preg_replace_callback(
- '/"(
+ '/"(?:(
[^"%!^]*+
(?:
(?: !LF! | "(?:\^[%!^])?+" )
[^"%!^]*+
)++
- )"/x',
+ ) | [^"]*+ )"/x',
function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) {
+ if (!isset($m[1])) {
+ return $m[0];
+ }
if (isset($varCache[$m[0]])) {
return $varCache[$m[0]];
}
diff --git a/src/Symfony/Component/Process/ProcessBuilder.php b/src/Symfony/Component/Process/ProcessBuilder.php
index 2a5bb2bc3f035..36db35edb5e43 100644
--- a/src/Symfony/Component/Process/ProcessBuilder.php
+++ b/src/Symfony/Component/Process/ProcessBuilder.php
@@ -272,6 +272,9 @@ public function getProcess()
$arguments = array_merge($this->prefix, $this->arguments);
$process = new Process($arguments, $this->cwd, $this->env, $this->input, $this->timeout, $this->options);
+ // to preserve the BC with symfony <3.3, we convert the array structure
+ // to a string structure to avoid the prefixing with the exec command
+ $process->setCommandLine($process->getCommandLine());
if ($this->inheritEnv) {
$process->inheritEnvironmentVariables();
diff --git a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php
index 34bb3732722e5..fa7c8c510adf3 100644
--- a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php
+++ b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php
@@ -210,4 +210,17 @@ public function testInvalidInput()
$builder = ProcessBuilder::create();
$builder->setInput(array());
}
+
+ public function testDoesNotPrefixExec()
+ {
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $this->markTestSkipped('This test cannot run on Windows.');
+ }
+
+ $builder = ProcessBuilder::create(array('command', '-v', 'ls'));
+ $process = $builder->getProcess();
+ $process->run();
+
+ $this->assertTrue($process->isSuccessful());
+ }
}
diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php
index e4d084f44efdb..267257117d43d 100644
--- a/src/Symfony/Component/Process/Tests/ProcessTest.php
+++ b/src/Symfony/Component/Process/Tests/ProcessTest.php
@@ -1484,6 +1484,24 @@ public function testEscapeArgumentWhenInheritEnvDisabled($arg)
$this->assertSame($arg, $p->getOutput());
}
+ public function testRawCommandLine()
+ {
+ $p = new Process(sprintf('"%s" -r %s "a" "" "b"', self::$phpBin, escapeshellarg('print_r($argv);')));
+ $p->run();
+
+ $expected = << -
+ [1] => a
+ [2] =>
+ [3] => b
+)
+
+EOTXT;
+ $this->assertSame($expected, $p->getOutput());
+ }
+
public function provideEscapeArgument()
{
yield array('a"b%c%');
diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json
index 8a7b33dbfddb0..4d6cac3ef98d9 100644
--- a/src/Symfony/Component/PropertyInfo/composer.json
+++ b/src/Symfony/Component/PropertyInfo/composer.json
@@ -34,7 +34,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",
"symfony/dependency-injection": "<3.3"
},
diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
index ce5cfa28477c4..1160deba49f42 100644
--- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
+++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php
@@ -81,9 +81,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 3f32238bffb7a..19828b63eca9a 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;
@@ -125,6 +128,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 4e4b99245da3c..25f5fffdc2dd4 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\ExtraAttributesException;
use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
@@ -54,8 +53,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 56d27eb7bf20f..62d59917d382c 100644
--- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php
@@ -33,8 +33,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());
diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php
index a0efa651b9258..b1e67cb30a035 100644
--- a/src/Symfony/Component/VarDumper/Caster/Caster.php
+++ b/src/Symfony/Component/VarDumper/Caster/Caster.php
@@ -65,11 +65,20 @@ public static function castObject($obj, $class, $hasDebugInfo = false)
}
if ($a) {
+ static $publicProperties = array();
+
$i = 0;
$prefixedKeys = array();
foreach ($a as $k => $v) {
- if (isset($k[0]) && "\0" !== $k[0] && !property_exists($class, $k)) {
- $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;
+ if (isset($k[0]) && "\0" !== $k[0]) {
+ if (!isset($publicProperties[$class])) {
+ foreach (get_class_vars($class) as $prop => $v) {
+ $publicProperties[$class][$prop] = true;
+ }
+ }
+ if (!isset($publicProperties[$class][$k])) {
+ $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k;
+ }
} elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) {
$prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0");
}
diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
index f1f58c0a87263..6786cf6a11803 100644
--- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
@@ -102,7 +102,7 @@ public static function castSilencedErrorContext(SilencedErrorContext $e, array $
}
unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']);
- $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace);
+ $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs);
return $a;
}
@@ -256,7 +256,7 @@ private static function filterExceptionArray($xClass, array $a, $xPrefix, $filte
$trace = array();
}
- if (!($filter & Caster::EXCLUDE_VERBOSE)) {
+ if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) {
if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) {
self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']);
}
diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
index c07ae491c5dc0..45e0b6ad771b1 100644
--- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
+++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
@@ -209,15 +209,17 @@ public function cloneVar($var, $filter = 0)
});
$this->filter = $filter;
+ if ($gc = gc_enabled()) {
+ gc_disable();
+ }
try {
$data = $this->doClone($var);
- } catch (\Exception $e) {
- }
- restore_error_handler();
- $this->prevErrorHandler = null;
-
- if (isset($e)) {
- throw $e;
+ } finally {
+ if ($gc) {
+ gc_enable();
+ }
+ restore_error_handler();
+ $this->prevErrorHandler = null;
}
return new Data($data);