diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md
index c93959532d398..cf90bc2e50f34 100644
--- a/CHANGELOG-2.7.md
+++ b/CHANGELOG-2.7.md
@@ -7,6 +7,36 @@ in 2.7 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/v2.7.0...v2.7.1
+* 2.7.30 (2017-07-03)
+
+ * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh)
+ * bug #23274 Display a better error design when the toolbar cannot be displayed (yceruto)
+ * bug #23333 [PropertyAccess] Fix TypeError discard (dunglas)
+ * bug #23345 [Console] fix description of INF default values (xabbuh)
+ * bug #23279 Don't call count on non countable object (pierredup)
+ * bug #23283 [TwigBundle] add back exception check (xabbuh)
+ * bug #23268 Show exception is checked twice in ExceptionController of twig (gmponos)
+ * bug #23266 Display a better error message when the toolbar cannot be displayed (javiereguiluz)
+ * bug #23271 [FrameworkBundle] allow SSI fragments configuration in XML files (xabbuh)
+ * bug #23254 [Form][TwigBridge] render hidden _method field in form_rest() (xabbuh)
+ * bug #23250 [Translation] return fallback locales whenever possible (xabbuh)
+ * bug #22732 [Security] fix switch user _exit without having current token (dmaicher)
+ * bug #22730 [FrameworkBundle] Sessions: configurable "use_strict_mode" option for NativeSessionStorage (MacDada)
+ * bug #23195 [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 (NicolasPion)
+ * bug #23052 [TwigBundle] Add Content-Type header for exception response (rchoquet)
+ * bug #23199 Reset redirectCount when throwing exception (hvanoch)
+ * bug #23186 [TwigBundle] Move template.xml loading to a compiler pass (ogizanagi)
+ * bug #23130 Keep s-maxage when expiry and validation are used in combination (mpdude)
+ * bug #23129 Fix two edge cases in ResponseCacheStrategy (mpdude)
+ * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL)
+ * bug #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL)
+ * bug #23057 [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 (mpdude)
+ * bug #23092 [Filesystem] added workaround in Filesystem::rename for PHP bug (VolCh)
+ * bug #23128 [HttpFoundation] fix for Support for new 7.1 session options (vincentaubert)
+ * bug #23176 [VarDumper] fixes (nicolas-grekas)
+ * bug #23086 [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() (nicolas-grekas)
+ * bug #23098 Cache ipCheck (2.7) (gonzalovilaseca)
+
* 2.7.29 (2017-06-07)
* bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 532b8a261c4f2..0b695308c528f 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -20,11 +20,11 @@ Symfony is the result of the work of many people who made the code better
- Javier Eguiluz (javier.eguiluz)
- Hugo Hamon (hhamon)
- Abdellatif Ait boudad (aitboudad)
+ - Maxime Steinhausser (ogizanagi)
+ - Robin Chalas (chalas_r)
- Romain Neutron (romain)
- Pascal Borreli (pborreli)
- Wouter De Jong (wouterj)
- - Robin Chalas (chalas_r)
- - Maxime Steinhausser (ogizanagi)
- Grégoire Pineau (lyrixx)
- Joseph Bielawski (stloyd)
- Karma Dordrak (drak)
@@ -38,8 +38,8 @@ Symfony is the result of the work of many people who made the code better
- Jules Pietri (heah)
- Roland Franssen (ro0)
- Sarah Khalil (saro0h)
- - Jonathan Wage (jwage)
- Guilhem Niot (energetick)
+ - Jonathan Wage (jwage)
- Diego Saint Esteben (dosten)
- Alexandre Salomé (alexandresalome)
- William Durand (couac)
@@ -48,24 +48,24 @@ Symfony is the result of the work of many people who made the code better
- stealth35 (stealth35)
- Alexander Mols (asm89)
- Bulat Shakirzyanov (avalanche123)
- - Peter Rehm (rpet)
- Iltar van der Berg (kjarli)
+ - Peter Rehm (rpet)
- Saša Stamenković (umpirsky)
- Henrik Bjørnskov (henrikbjorn)
- Miha Vrhovnik
- Diego Saint Esteben (dii3g0)
- Konstantin Kudryashov (everzet)
+ - Matthias Pigulla (mpdude)
- Bilal Amarni (bamarni)
- Florin Patan (florinpatan)
- - Matthias Pigulla (mpdude)
+ - Gábor Egyed (1ed)
- Kevin Bond (kbond)
- Andrej Hudec (pulzarraider)
- - Gábor Egyed (1ed)
+ - Pierre du Plessis (pierredup)
- Michel Weimerskirch (mweimerskirch)
- Eric Clemmons (ericclemmons)
- Charles Sarrazin (csarrazi)
- Christian Raue
- - Pierre du Plessis (pierredup)
- Arnout Boks (aboks)
- Deni
- Henrik Westphal (snc)
@@ -83,25 +83,27 @@ Symfony is the result of the work of many people who made the code better
- Toni Uebernickel (havvg)
- Bart van den Burg (burgov)
- Jordan Alliot (jalliot)
+ - Jérôme Tamarelle (gromnan)
- John Wards (johnwards)
- Dariusz Ruminski
- Fran Moreno (franmomu)
- Antoine Hérault (herzult)
- - Jérôme Tamarelle (gromnan)
- Paráda József (paradajozsef)
- Arnaud Le Blanc (arnaud-lb)
- Maxime STEINHAUSSER
+ - Alexander M. Turek (derrabus)
- Michal Piotrowski (eventhorizon)
- Issei Murasawa (issei_m)
- Tim Nagel (merk)
- Brice BERNARD (brikou)
- - Alexander M. Turek (derrabus)
- Baptiste Clavié (talus)
+ - Vladimir Reznichenko (kalessil)
- marc.weistroff
- lenar
- Włodzimierz Gajda (gajdaw)
- - Vladimir Reznichenko (kalessil)
+ - Yonel Ceruto González (yonelceruto)
- Alexander Schwenn (xelaris)
+ - Jacob Dreesen (jdreesen)
- Florian Voutzinos (florianv)
- Colin Frei
- Adrien Brault (adrienbrault)
@@ -109,10 +111,8 @@ Symfony is the result of the work of many people who made the code better
- Peter Kokot (maastermedia)
- David Buchmann (dbu)
- excelwebzone
- - Jacob Dreesen (jdreesen)
- Tobias Nyholm (tobias)
- Tomáš Votruba (tomas_votruba)
- - Yonel Ceruto González (yonelceruto)
- Fabien Pennequin (fabienpennequin)
- Gordon Franke (gimler)
- Eric GELOEN (gelo)
@@ -124,13 +124,13 @@ Symfony is the result of the work of many people who made the code better
- Sebastiaan Stok (sstok)
- Stefano Sala (stefano.sala)
- Evgeniy (ewgraf)
+ - Vincent AUBERT (vincent)
- Juti Noppornpitak (shiroyuki)
- Tigran Azatyan (tigranazatyan)
- Sebastian Hörl (blogsh)
- Daniel Gomes (danielcsgomes)
- Hidenori Goto (hidenorigoto)
- Guilherme Blanco (guilhermeblanco)
- - Vincent AUBERT (vincent)
- Pablo Godel (pgodel)
- Jérémie Augustin (jaugustin)
- Andréia Bohner (andreia)
@@ -147,6 +147,7 @@ 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
@@ -154,16 +155,16 @@ Symfony is the result of the work of many people who made the code better
- Hiromi Hishida (77web)
- Matthieu Ouellette-Vachon (maoueh)
- Michał Pipa (michal.pipa)
+ - Dawid Nowak
- Amal Raghav (kertz)
- Jonathan Ingram (jonathaningram)
- Artur Kotyrba
- - David Maicher (dmaicher)
- jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent)
- James Halsall (jaitsu)
- Warnar Boekkooi (boekkooi)
- Dmitrii Chekaliuk (lazyhammer)
- Clément JOBEILI (dator)
- - Dawid Nowak
+ - Lars Strojny (lstrojny)
- Possum
- Dorian Villet (gnutix)
- Richard Miller (mr_r_miller)
@@ -175,12 +176,12 @@ Symfony is the result of the work of many people who made the code better
- Chris Wilkinson (thewilkybarkid)
- Andreas Hucks (meandmymonkey)
- Noel Guilbert (noel)
- - Lars Strojny (lstrojny)
- Stepan Anchugov (kix)
- bronze1man
- Daniel Espendiller
- sun (sun)
- Larry Garfield (crell)
+ - Oleg Voronkovich
- Martin Schuhfuß (usefulthink)
- apetitpa
- Matthieu Bontemps (mbontemps)
@@ -242,7 +243,6 @@ Symfony is the result of the work of many people who made the code better
- Uwe Jäger (uwej711)
- Eugene Leonovich (rybakit)
- Filippo Tessarotto
- - Oleg Voronkovich
- Joseph Rouff (rouffj)
- Félix Labrecque (woodspire)
- GordonsLondon
@@ -294,6 +294,7 @@ Symfony is the result of the work of many people who made the code better
- Victor Bocharsky (bocharsky_bw)
- Jan Decavele (jandc)
- Gustavo Piltcher
+ - Nikolay Labinskiy (e-moe)
- Stepan Tanasiychuk (stfalcon)
- Tiago Ribeiro (fixe)
- Hidde Boomsma (hboomsma)
@@ -359,7 +360,6 @@ Symfony is the result of the work of many people who made the code better
- Endre Fejes
- Tobias Naumann (tna)
- Daniel Beyer
- - Nikolay Labinskiy (e-moe)
- Shein Alexey
- Romain Gautier (mykiwi)
- Joe Lencioni
@@ -609,6 +609,7 @@ Symfony is the result of the work of many people who made the code better
- Kevin (oxfouzer)
- Paweł Wacławczyk (pwc)
- Oleg Zinchenko (cystbear)
+ - Baptiste Meyer (meyerbaptiste)
- Johannes Klauss (cloppy)
- Evan Villemez
- fzerorubigd
@@ -671,6 +672,7 @@ Symfony is the result of the work of many people who made the code better
- Benoit Lévêque (benoit_leveque)
- Jeroen Fiege (fieg)
- Krzysiek Łabuś
+ - George Mponos (gmponos)
- Xavier Lacot (xavier)
- possum
- Denis Zunke (donalberto)
@@ -734,6 +736,7 @@ Symfony is the result of the work of many people who made the code better
- Omar Yepez (oyepez003)
- mwsaz
- Jelle Kapitein
+ - Ben Scott
- Benoît Bourgeois
- mantulo
- corphi
@@ -815,6 +818,7 @@ Symfony is the result of the work of many people who made the code better
- ttomor
- Mei Gwilym (meigwilym)
- Michael H. Arieli (excelwebzone)
+ - Tom Panier (neemzy)
- Fred Cox
- Luciano Mammino (loige)
- fabios
@@ -850,6 +854,7 @@ Symfony is the result of the work of many people who made the code better
- Máximo Cuadros (mcuadros)
- tamirvs
- julien.galenski
+ - Israel J. Carberry
- Bob van de Vijver
- Christian Neff
- Per Sandström (per)
@@ -888,7 +893,6 @@ Symfony is the result of the work of many people who made the code better
- Eddie Jaoude
- Antanas Arvasevicius
- Haritz Iturbe (hizai)
- - Baptiste Meyer (meyerbaptiste)
- Nerijus Arlauskas (nercury)
- SPolischook
- Diego Sapriza
@@ -910,8 +914,10 @@ Symfony is the result of the work of many people who made the code better
- Marcin Chwedziak
- hjkl
- Tony Cosentino (tony-co)
+ - Dan Wilga
- Alexander Cheprasov
- Rodrigo Díez Villamuera (rodrigodiez)
+ - Malte Blättermann
- e-ivanov
- Jochen Bayer (jocl)
- Jeremy Bush
@@ -923,12 +929,14 @@ Symfony is the result of the work of many people who made the code better
- Péter Buri (burci)
- Davide Borsatto (davide.borsatto)
- kaiwa
+ - RJ Garcia
- Charles Sanquer (csanquer)
- Albert Ganiev (helios-ag)
- Neil Katin
- David Otton
- Will Donohoe
- peter
+ - Jaroslav Kuba
- flip111
- Jérémy Jourdin (jjk801)
- BRAMILLE Sébastien (oktapodia)
@@ -936,6 +944,7 @@ Symfony is the result of the work of many people who made the code better
- Gustavo Adrian
- Yannick
- spdionis
+ - rchoquet
- Taras Girnyk
- Eduardo García Sanz (coma)
- James Gilliland
@@ -965,6 +974,7 @@ Symfony is the result of the work of many people who made the code better
- Paul Matthews
- Juan Traverso
- Tarjei Huse (tarjei)
+ - tsufeki
- Philipp Strube
- Christian Sciberras
- Clement Herreman (clemherreman)
@@ -1055,6 +1065,7 @@ Symfony is the result of the work of many people who made the code better
- m.chwedziak
- Philip Frank
- Lance McNearney
+ - Gonzalo Vilaseca (gonzalovilaseca)
- Giorgio Premi
- Ian Carroll
- caponica
@@ -1065,7 +1076,6 @@ Symfony is the result of the work of many people who made the code better
- adev
- Luis Galeas
- Martin Pärtel
- - George Mponos (gmponos)
- Patrick Daley (padrig)
- Xavier Briand (xavierbriand)
- Max Summe
@@ -1146,6 +1156,7 @@ Symfony is the result of the work of many people who made the code better
- Hoffmann András
- Olivier
- pscheit
+ - Wybren Koelmans
- Zdeněk Drahoš
- Dan Harper
- moldcraft
@@ -1233,6 +1244,7 @@ Symfony is the result of the work of many people who made the code better
- Fabien LUCAS (flucas2)
- Indra Gunawan (indragunawan)
- Karim Cassam Chenaï (ka)
+ - Michal Kurzeja (mkurzeja)
- Nicolas Bastien (nicolas_bastien)
- Denis (yethee)
- Andrew Zhilin (zhil)
@@ -1251,9 +1263,11 @@ Symfony is the result of the work of many people who made the code better
- Warwick
- VJ
- Chris
+ - Florent Olivaud
- JakeFr
- Simon Sargeant
- efeen
+ - Nicolas Pion
- Muhammed Akbulut
- Michał Dąbrowski (defrag)
- Simone Fumagalli (hpatoio)
@@ -1270,6 +1284,7 @@ Symfony is the result of the work of many people who made the code better
- Grinbergs Reinis (shima5)
- Artem Lopata (bumz)
- Nicole Cordes
+ - VolCh
- Alexey Popkov
- Gijs Kunze
- Artyom Protaskin
@@ -1375,6 +1390,7 @@ Symfony is the result of the work of many people who made the code better
- Dane Powell
- Gerrit Drost
- Linnaea Von Lavia
+ - Javan Eskander
- Lenar Lõhmus
- Cristian Gonzalez
- AlberT
@@ -1423,7 +1439,6 @@ Symfony is the result of the work of many people who made the code better
- Yanick Witschi
- Ondrej Mirtes
- akimsko
- - Ben Scott
- Youpie
- srsbiz
- Taylan Kasap
@@ -1556,6 +1571,7 @@ Symfony is the result of the work of many people who made the code better
- Dawid Nowak
- Lesnykh Ilia
- Karolis Daužickas
+ - Nicolas
- Sergio Santoro
- tirnanog06
- phc
@@ -1689,6 +1705,7 @@ Symfony is the result of the work of many people who made the code better
- Adam Elsodaney (archfizz)
- Daniel Kolvik (dkvk)
- Marc Lemay (flug)
+ - Henne Van Och (hennevo)
- Jeroen De Dauw (jeroendedauw)
- Maxime COLIN (maximecolin)
- Muharrem Demirci (mdemirci)
diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
index 51181b0714e47..b0d9534a0e98d 100644
--- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
+++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php
@@ -62,6 +62,10 @@ public function validate($entity, Constraint $constraint)
throw new ConstraintDefinitionException('At least one field has to be specified.');
}
+ if (null === $entity) {
+ return;
+ }
+
if ($constraint->em) {
$em = $this->registry->getManager($constraint->em);
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
index 04988d1539b24..0a52cc5110c82 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
@@ -262,6 +262,7 @@
{%- endblock form -%}
{%- block form_start -%}
+ {%- do form.setMethodRendered() -%}
{% set method = method|upper %}
{%- if method in ["GET", "POST"] -%}
{% set form_method = method %}
@@ -301,6 +302,20 @@
{{- form_row(child) -}}
{% endif %}
{%- endfor %}
+
+ {% if not form.methodRendered %}
+ {%- do form.setMethodRendered() -%}
+ {% set method = method|upper %}
+ {%- if method in ["GET", "POST"] -%}
+ {% set form_method = method %}
+ {%- else -%}
+ {% set form_method = "POST" %}
+ {%- endif -%}
+
+ {%- if form_method != method -%}
+
+ {%- endif -%}
+ {% endif %}
{% endblock form_rest %}
{# Support #}
diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json
index 3b6c4356e14ba..9610edc8085b5 100644
--- a/src/Symfony/Bridge/Twig/composer.json
+++ b/src/Symfony/Bridge/Twig/composer.json
@@ -22,7 +22,7 @@
"require-dev": {
"symfony/asset": "~2.7",
"symfony/finder": "~2.3",
- "symfony/form": "~2.7.26|^2.8.19",
+ "symfony/form": "~2.7.30|^2.8.23",
"symfony/http-kernel": "~2.3",
"symfony/intl": "~2.3",
"symfony/routing": "~2.2",
@@ -36,6 +36,9 @@
"symfony/var-dumper": "~2.7.16|^2.8.9",
"symfony/expression-language": "~2.4"
},
+ "conflict": {
+ "symfony/form": "<2.7.30|~2.8,<2.8.23"
+ },
"suggest": {
"symfony/finder": "",
"symfony/asset": "For using the AssetExtension",
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
index 94daa82cc9a26..0a3ea2871deb3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
@@ -89,6 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$output->writeln('Installing assets as hard copies.');
}
+ $validAssetDirs = array();
foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) {
if (is_dir($originDir = $bundle->getPath().'/Resources/public')) {
$targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
@@ -131,6 +132,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
} else {
$this->hardCopy($originDir, $targetDir);
}
+ $validAssetDirs[] = $targetDir;
+ }
+ }
+ // remove the assets of the bundles that no longer exist
+ foreach (new \FilesystemIterator($bundlesDir) as $dir) {
+ if (!in_array($dir, $validAssetDirs)) {
+ $filesystem->remove($dir);
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
index 84c2fae7d4db8..5e9014bfc5ddd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
@@ -141,7 +141,7 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr
$safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel));
$realKernelFQN = get_class($realKernel);
- foreach (Finder::create()->files()->name('*.meta')->in($warmupDir) as $file) {
+ foreach (Finder::create()->files()->depth('<3')->name('*.meta')->in($warmupDir) as $file) {
file_put_contents($file, preg_replace(
'/(C\:\d+\:)"'.$safeTempKernel.'"/',
sprintf('$1"%s"', $realKernelFQN),
@@ -153,14 +153,16 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr
$search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir));
$replace = str_replace('\\', '/', $realCacheDir);
foreach (Finder::create()->files()->in($warmupDir) as $file) {
- $content = str_replace($search, $replace, file_get_contents($file));
- file_put_contents($file, $content);
+ $content = str_replace($search, $replace, file_get_contents($file), $count);
+ if ($count) {
+ file_put_contents($file, $content);
+ }
}
// fix references to container's class
$tempContainerClass = get_class($tempKernel->getContainer());
$realContainerClass = get_class($realKernel->getContainer());
- foreach (Finder::create()->files()->name($tempContainerClass.'*')->in($warmupDir) as $file) {
+ foreach (Finder::create()->files()->depth('<2')->name($tempContainerClass.'*')->in($warmupDir) as $file) {
$content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file));
file_put_contents($file, $content);
rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file));
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index b21b3ee8df769..404bd60ced98d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -348,6 +348,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
->scalarNode('gc_divisor')->end()
->scalarNode('gc_probability')->defaultValue(1)->end()
->scalarNode('gc_maxlifetime')->end()
+ ->booleanNode('use_strict_mode')->end()
->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end()
->integerNode('metadata_update_threshold')
->defaultValue('0')
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 3d125d616d393..85a1a9ba208f3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -402,7 +402,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c
// session storage
$container->setAlias('session.storage', $config['storage_id']);
$options = array();
- foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) {
+ foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'use_strict_mode') as $key) {
if (isset($config[$key])) {
$options[$key] = $config[$key];
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index fa7aa2b2bd808..2d866ff1b5cac 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -22,6 +22,7 @@
+
@@ -64,6 +65,10 @@
+
+
+
+
@@ -111,6 +116,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php
index 6acc04539393d..172417924c921 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php
@@ -78,7 +78,7 @@ public function getVersion($path = null, $packageName = null)
// packageName is null and path not, so path is a path or a packageName
try {
- $package = $this->packages->getPackage($path);
+ $this->packages->getPackage($path);
} catch (\InvalidArgumentException $e) {
// path is not a package, so it should be a path
return $this->packages->getVersion($path);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
index 5022aeaf9f207..6861844b49233 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
@@ -16,6 +16,9 @@
'esi' => array(
'enabled' => true,
),
+ 'ssi' => array(
+ 'enabled' => true,
+ ),
'profiler' => array(
'only_exceptions' => true,
'enabled' => false,
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
index 5b16a59796091..c0d8a85a1c5d7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
@@ -12,6 +12,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
index 47dcb575317e3..3e000ca9cc59c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
@@ -10,6 +10,8 @@ framework:
enabled: true
esi:
enabled: true
+ ssi:
+ enabled: true
profiler:
only_exceptions: true
enabled: false
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index a782a3f0748bb..5601e6a88b236 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -98,6 +98,13 @@ public function testEsi()
$this->assertTrue($container->hasDefinition('esi'), '->registerEsiConfiguration() loads esi.xml');
}
+ public function testSsi()
+ {
+ $container = $this->createContainerFromFile('full');
+
+ $this->assertTrue($container->hasDefinition('ssi'), '->registerSsiConfiguration() loads ssi.xml');
+ }
+
public function testEnabledProfiler()
{
$container = $this->createContainerFromFile('profiler');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
index 361bcf001b560..75f4281952227 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php
@@ -135,6 +135,51 @@ public function testGetDefaultLocale()
$this->assertSame('en', $translator->getLocale());
}
+ /** @dataProvider getDebugModeAndCacheDirCombinations */
+ public function testResourceFilesOptionLoadsBeforeOtherAddedResources($debug, $enableCache)
+ {
+ $someCatalogue = $this->getCatalogue('some_locale', array());
+
+ $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock();
+
+ $loader->expects($this->at(0))
+ ->method('load')
+ /* The "messages.some_locale.loader" is passed via the resource_file option and shall be loaded first */
+ ->with('messages.some_locale.loader', 'some_locale', 'messages')
+ ->willReturn($someCatalogue);
+
+ $loader->expects($this->at(1))
+ ->method('load')
+ /* This resource is added by an addResource() call and shall be loaded after the resource_files */
+ ->with('second_resource.some_locale.loader', 'some_locale', 'messages')
+ ->willReturn($someCatalogue);
+
+ $options = array(
+ 'resource_files' => array('some_locale' => array('messages.some_locale.loader')),
+ 'debug' => $debug,
+ );
+
+ if ($enableCache) {
+ $options['cache_dir'] = $this->tmpDir;
+ }
+
+ /** @var Translator $translator */
+ $translator = $this->createTranslator($loader, $options);
+ $translator->addResource('loader', 'second_resource.some_locale.loader', 'some_locale', 'messages');
+
+ $translator->trans('some_message', array(), null, 'some_locale');
+ }
+
+ public function getDebugModeAndCacheDirCombinations()
+ {
+ return array(
+ array(false, false),
+ array(true, false),
+ array(false, true),
+ array(true, true),
+ );
+ }
+
protected function getCatalogue($locale, $messages, $resources = array())
{
$catalogue = new MessageCatalogue($locale);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
index fba6d70d6978b..9fdfb645d372a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
@@ -37,6 +37,14 @@ class Translator extends BaseTranslator implements WarmableInterface
*/
private $resourceLocales;
+ /**
+ * Holds parameters from addResource() calls so we can defer the actual
+ * parent::addResource() calls until initialize() is executed.
+ *
+ * @var array
+ */
+ private $resources = array();
+
/**
* Constructor.
*
@@ -65,9 +73,7 @@ public function __construct(ContainerInterface $container, MessageSelector $sele
$this->options = array_merge($this->options, $options);
$this->resourceLocales = array_keys($this->options['resource_files']);
- if (null !== $this->options['cache_dir'] && $this->options['debug']) {
- $this->loadResources();
- }
+ $this->addResourceFiles($this->options['resource_files']);
parent::__construct($container->getParameter('kernel.default_locale'), $selector, $this->options['cache_dir'], $this->options['debug']);
}
@@ -93,6 +99,11 @@ public function warmUp($cacheDir)
}
}
+ public function addResource($format, $resource, $locale, $domain = null)
+ {
+ $this->resources[] = array($format, $resource, $locale, $domain);
+ }
+
/**
* {@inheritdoc}
*/
@@ -104,7 +115,12 @@ protected function initializeCatalogue($locale)
protected function initialize()
{
- $this->loadResources();
+ foreach ($this->resources as $key => $params) {
+ list($format, $resource, $locale, $domain) = $params;
+ parent::addResource($format, $resource, $locale, $domain);
+ }
+ $this->resources = array();
+
foreach ($this->loaderIds as $id => $aliases) {
foreach ($aliases as $alias) {
$this->addLoader($alias, $this->container->get($id));
@@ -112,14 +128,13 @@ protected function initialize()
}
}
- private function loadResources()
+ private function addResourceFiles($filesByLocale)
{
- foreach ($this->options['resource_files'] as $locale => $files) {
+ foreach ($filesByLocale as $locale => $files) {
foreach ($files as $key => $file) {
// filename is domain.locale.format
list($domain, $locale, $format) = explode('.', basename($file), 3);
$this->addResource($format, $file, $locale, $domain);
- unset($this->options['resource_files'][$locale][$key]);
}
}
}
diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
index 0eab87de26e2b..1878204003b62 100644
--- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
+++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
@@ -74,7 +74,7 @@ public function showAction(Request $request, FlattenException $exception, DebugL
'logger' => $logger,
'currentContent' => $currentContent,
)
- ));
+ ), 200, array('Content-Type' => $request->getMimeType($request->getRequestFormat()) ?: 'text/html'));
}
/**
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php
index ab9479e46166a..c829cfa4377fb 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php
@@ -96,6 +96,7 @@ public function process(ContainerBuilder $container)
$twigLoader->clearTag('twig.loader');
} else {
$container->setAlias('twig.loader.filesystem', new Alias('twig.loader.native_filesystem', false));
+ $container->removeDefinition('templating.engine.twig');
}
if ($container->has('assets.packages')) {
diff --git a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php
index 68a7b4560c95d..b92764d371bf4 100644
--- a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php
+++ b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php
@@ -75,7 +75,6 @@ protected function findTemplate($template, $throw = true)
}
$file = null;
- $previous = null;
try {
$file = parent::findTemplate($logicalName);
} catch (LoaderError $e) {
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php
index 17f3ac17c87f2..82f10c8296fd2 100644
--- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php
+++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php
@@ -22,14 +22,9 @@ class ExceptionControllerTest extends TestCase
{
public function testShowActionCanBeForcedToShowErrorPage()
{
- $twig = new Environment(
- new ArrayLoader(array(
- 'TwigBundle:Exception:error404.html.twig' => 'ok',
- ))
- );
+ $twig = $this->createTwigEnv(array('TwigBundle:Exception:error404.html.twig' => 'not found'));
- $request = Request::create('whatever', 'GET');
- $request->headers->set('X-Php-Ob-Level', 1);
+ $request = $this->createRequest('html');
$request->attributes->set('showException', false);
$exception = FlattenException::create(new \Exception(), 404);
$controller = new ExceptionController($twig, /* "showException" defaults to --> */ true);
@@ -37,25 +32,61 @@ public function testShowActionCanBeForcedToShowErrorPage()
$response = $controller->showAction($request, $exception, null);
$this->assertEquals(200, $response->getStatusCode()); // successful request
- $this->assertEquals('ok', $response->getContent()); // content of the error404.html template
+ $this->assertEquals('not found', $response->getContent());
}
public function testFallbackToHtmlIfNoTemplateForRequestedFormat()
{
- $twig = new Environment(
- new ArrayLoader(array(
- 'TwigBundle:Exception:error.html.twig' => 'html',
- ))
- );
+ $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.html.twig' => ''));
- $request = Request::create('whatever');
- $request->headers->set('X-Php-Ob-Level', 1);
- $request->setRequestFormat('txt');
+ $request = $this->createRequest('txt');
$exception = FlattenException::create(new \Exception());
$controller = new ExceptionController($twig, false);
- $response = $controller->showAction($request, $exception);
+ $controller->showAction($request, $exception);
+
+ $this->assertEquals('html', $request->getRequestFormat());
+ }
+
+ public function testFallbackToHtmlWithFullExceptionIfNoTemplateForRequestedFormatAndExceptionsShouldBeShown()
+ {
+ $twig = $this->createTwigEnv(array('TwigBundle:Exception:exception_full.html.twig' => ''));
+
+ $request = $this->createRequest('txt');
+ $request->attributes->set('showException', true);
+ $exception = FlattenException::create(new \Exception());
+ $controller = new ExceptionController($twig, false);
+
+ $controller->showAction($request, $exception);
$this->assertEquals('html', $request->getRequestFormat());
}
+
+ public function testResponseHasRequestedMimeType()
+ {
+ $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.json.twig' => '{}'));
+
+ $request = $this->createRequest('json');
+ $exception = FlattenException::create(new \Exception());
+ $controller = new ExceptionController($twig, false);
+
+ $response = $controller->showAction($request, $exception);
+
+ $this->assertEquals('json', $request->getRequestFormat());
+ $this->assertEquals($request->getMimeType('json'), $response->headers->get('Content-Type'));
+ }
+
+ private function createRequest($requestFormat)
+ {
+ $request = Request::create('whatever');
+ $request->headers->set('X-Php-Ob-Level', 1);
+ $request->setRequestFormat($requestFormat);
+
+ return $request;
+ }
+
+ private function createTwigEnv(array $templates)
+ {
+ return new Environment(new ArrayLoader($templates));
+ }
}
diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
index fb82ee8266dbf..f5809cc045c42 100644
--- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
+++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php
@@ -170,9 +170,10 @@ public function testGlobalsWithDifferentTypesAndValues()
$calls = $container->getDefinition('twig')->getMethodCalls();
foreach (array_slice($calls, 1) as $call) {
- list($name, $value) = each($globals);
- $this->assertEquals($name, $call[1][0]);
- $this->assertSame($value, $call[1][1]);
+ $this->assertEquals(key($globals), $call[1][0]);
+ $this->assertSame(current($globals), $call[1][1]);
+
+ next($globals);
}
}
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 a01a9017f4a49..2e05fb89abe71 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig
@@ -440,3 +440,33 @@
visibility: hidden;
}
}
+
+/***** Error Toolbar *****/
+.sf-error-toolbar .sf-toolbarreset {
+ background: #222;
+ color: #f5f5f5;
+ font: 13px/36px Arial, sans-serif;
+ height: 36px;
+ padding: 0 15px;
+ text-align: left;
+}
+
+.sf-error-toolbar .sf-toolbarreset svg {
+ height: auto;
+}
+
+.sf-error-toolbar .sf-toolbarreset a {
+ color: #99cdd8;
+ margin-left: 5px;
+ text-decoration: underline;
+}
+
+.sf-error-toolbar .sf-toolbarreset a:hover {
+ text-decoration: none;
+}
+
+.sf-error-toolbar .sf-toolbarreset .sf-toolbar-icon {
+ float: left;
+ padding: 5px 0;
+ margin-right: 10px;
+}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig
index 91ad9ad10ecf1..3bdd8ef1e843e 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig
@@ -58,7 +58,14 @@
},
function(xhr) {
if (xhr.status !== 0) {
- confirm('An error occurred while loading the web debug toolbar (' + xhr.status + ': ' + xhr.statusText + ').\n\nDo you want to open the profiler?') && (window.location = '{{ path("_profiler", { "token": token }) }}');
+ var sfwdt = document.getElementById('sfwdt{{ token }}');
+ sfwdt.innerHTML = '\
+
\
+ \
+ An error occurred while loading the web debug toolbar. Open the web profiler.\
+
\
+ ';
+ sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar');
}
},
{'maxTries': 5}
diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php
index c69599083802d..b5b2dab50d4cc 100644
--- a/src/Symfony/Component/BrowserKit/Client.php
+++ b/src/Symfony/Component/BrowserKit/Client.php
@@ -448,6 +448,7 @@ public function followRedirect()
if (-1 !== $this->maxRedirects) {
if ($this->redirectCount > $this->maxRedirects) {
+ $this->redirectCount = 0;
throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects));
}
}
diff --git a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php
index 87e38fdb89071..942fdc96226ac 100644
--- a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php
+++ b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php
@@ -103,7 +103,7 @@ private function getInputArgumentData(InputArgument $argument)
'is_required' => $argument->isRequired(),
'is_array' => $argument->isArray(),
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
- 'default' => $argument->getDefault(),
+ 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
);
}
@@ -121,7 +121,7 @@ private function getInputOptionData(InputOption $option)
'is_value_required' => $option->isValueRequired(),
'is_multiple' => $option->isArray(),
'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
- 'default' => $option->getDefault(),
+ 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
);
}
diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php
index c0dd4830c3d2d..5b82b3deefa8e 100644
--- a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php
+++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php
@@ -237,6 +237,10 @@ private function writeText($content, array $options = array())
*/
private function formatDefaultValue($default)
{
+ if (INF === $default) {
+ return 'INF';
+ }
+
if (is_string($default)) {
$default = OutputFormatter::escape($default);
} elseif (is_array($default)) {
diff --git a/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php
index 8f825ecb68395..b4f34ada19ec6 100644
--- a/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php
+++ b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php
@@ -32,6 +32,7 @@ public static function getInputArguments()
'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'),
'input_argument_4' => new InputArgument('argument_name', InputArgument::REQUIRED, "multiline\nargument description"),
'input_argument_with_style' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'style>'),
+ 'input_argument_with_default_inf_value' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', INF),
);
}
@@ -46,6 +47,7 @@ public static function getInputOptions()
'input_option_6' => new InputOption('option_name', array('o', 'O'), InputOption::VALUE_REQUIRED, 'option with multiple shortcuts'),
'input_option_with_style' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description', 'style>'),
'input_option_with_style_array' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'option description', array('Hello', 'world')),
+ 'input_option_with_default_inf_value' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', INF),
);
}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json
new file mode 100644
index 0000000000000..b61ecf7b8c23c
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json
@@ -0,0 +1,7 @@
+{
+ "name": "argument_name",
+ "is_required": false,
+ "is_array": false,
+ "description": "argument description",
+ "default": "INF"
+}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md
new file mode 100644
index 0000000000000..293d816201271
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md
@@ -0,0 +1,7 @@
+**argument_name:**
+
+* Name: argument_name
+* Is required: no
+* Is array: no
+* Description: argument description
+* Default: `INF`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt
new file mode 100644
index 0000000000000..c32d768c6f328
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt
@@ -0,0 +1 @@
+ argument_name argument description [default: INF]
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml
new file mode 100644
index 0000000000000..d457260070be0
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml
@@ -0,0 +1,7 @@
+
+
+ argument description
+
+ INF
+
+
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json
new file mode 100644
index 0000000000000..7c96ad30405c6
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json
@@ -0,0 +1,9 @@
+{
+ "name": "--option_name",
+ "shortcut": "-o",
+ "accept_value": true,
+ "is_value_required": false,
+ "is_multiple": false,
+ "description": "option description",
+ "default": "INF"
+}
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md
new file mode 100644
index 0000000000000..b57bd04bf9993
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md
@@ -0,0 +1,9 @@
+**option_name:**
+
+* Name: `--option_name`
+* Shortcut: `-o`
+* Accept value: yes
+* Is value required: no
+* Is multiple: no
+* Description: option description
+* Default: `INF`
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt
new file mode 100644
index 0000000000000..d467dcf42327b
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt
@@ -0,0 +1 @@
+ -o, --option_name[=OPTION_NAME] option description [default: INF]
diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml
new file mode 100644
index 0000000000000..5d1d21753e9dc
--- /dev/null
+++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml
@@ -0,0 +1,7 @@
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
index cefe0a02aa829..f4274b80a4443 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
@@ -108,7 +108,7 @@ public function testGet()
}
$builder->register('foobar', 'stdClass')->setScope('container');
- $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared');
+ $this->assertSame($builder->get('bar'), $builder->get('bar'), '->get() always returns the same instance if the service is shared');
}
/**
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index edfc1b9d46a23..e60d4690738ad 100644
--- a/src/Symfony/Component/Filesystem/Filesystem.php
+++ b/src/Symfony/Component/Filesystem/Filesystem.php
@@ -276,6 +276,13 @@ public function rename($origin, $target, $overwrite = false)
}
if (true !== @rename($origin, $target)) {
+ if (is_dir($origin)) {
+ // See https://bugs.php.net/bug.php?id=54097 & http://php.net/manual/en/function.rename.php#113943
+ $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
+ $this->remove($origin);
+
+ return;
+ }
throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
}
}
diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php
index 0791cebc694b8..9ed871ea5a2a3 100644
--- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php
+++ b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php
@@ -49,7 +49,7 @@ public function testErrorHandlingInLockIfLockPathBecomesUnwritable()
$this->markTestSkipped('This test cannot run on Windows.');
}
- $lockPath = sys_get_temp_dir().'/'.uniqid();
+ $lockPath = sys_get_temp_dir().'/'.uniqid('', true);
$e = null;
$wrongMessage = null;
diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php
index e08c9e51276be..fd24ccbeb11da 100644
--- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php
+++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php
@@ -89,7 +89,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null,
if (!is_callable($preferredChoices) && !empty($preferredChoices)) {
$preferredChoices = function ($choice) use ($preferredChoices) {
- return false !== array_search($choice, $preferredChoices, true);
+ return in_array($choice, $preferredChoices, true);
};
}
diff --git a/src/Symfony/Component/Form/FormBuilderInterface.php b/src/Symfony/Component/Form/FormBuilderInterface.php
index 1145ab26420c0..c19cc903beeba 100644
--- a/src/Symfony/Component/Form/FormBuilderInterface.php
+++ b/src/Symfony/Component/Form/FormBuilderInterface.php
@@ -27,7 +27,7 @@ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuild
* @param string|FormTypeInterface $type
* @param array $options
*
- * @return $this
+ * @return self
*/
public function add($child, $type = null, array $options = array());
@@ -58,7 +58,7 @@ public function get($name);
*
* @param string $name
*
- * @return $this
+ * @return self
*/
public function remove($name);
diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php
index 15a8d08430cfe..9d1c075bb5fa7 100644
--- a/src/Symfony/Component/Form/FormRenderer.php
+++ b/src/Symfony/Component/Form/FormRenderer.php
@@ -316,6 +316,6 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va
*/
public function humanize($text)
{
- return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text))));
+ return ucfirst(strtolower(trim(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text))));
}
}
diff --git a/src/Symfony/Component/Form/FormView.php b/src/Symfony/Component/Form/FormView.php
index c1da5f8fc9bb1..8655bedf6e135 100644
--- a/src/Symfony/Component/Form/FormView.php
+++ b/src/Symfony/Component/Form/FormView.php
@@ -53,6 +53,8 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable
*/
private $rendered = false;
+ private $methodRendered = false;
+
public function __construct(FormView $parent = null)
{
$this->parent = $parent;
@@ -90,6 +92,19 @@ public function setRendered()
return $this;
}
+ /**
+ * @return bool
+ */
+ public function isMethodRendered()
+ {
+ return $this->methodRendered;
+ }
+
+ public function setMethodRendered()
+ {
+ $this->methodRendered = true;
+ }
+
/**
* Returns a child by name (implements \ArrayAccess).
*
diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php
index fc0dee140b047..47f9e43294ba0 100644
--- a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener;
use PHPUnit\Framework\TestCase;
-use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener;
diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php
index 28093be43403f..eba603b15df01 100644
--- a/src/Symfony/Component/HttpFoundation/IpUtils.php
+++ b/src/Symfony/Component/HttpFoundation/IpUtils.php
@@ -18,6 +18,8 @@
*/
class IpUtils
{
+ private static $checkedIps = array();
+
/**
* This class should not be instantiated.
*/
@@ -61,26 +63,31 @@ public static function checkIp($requestIp, $ips)
*/
public static function checkIp4($requestIp, $ip)
{
+ $cacheKey = $requestIp.'-'.$ip;
+ if (isset(self::$checkedIps[$cacheKey])) {
+ return self::$checkedIps[$cacheKey];
+ }
+
if (!filter_var($requestIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
- return false;
+ return self::$checkedIps[$cacheKey] = false;
}
if (false !== strpos($ip, '/')) {
list($address, $netmask) = explode('/', $ip, 2);
if ($netmask === '0') {
- return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
+ return self::$checkedIps[$cacheKey] = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
}
if ($netmask < 0 || $netmask > 32) {
- return false;
+ return self::$checkedIps[$cacheKey] = false;
}
} else {
$address = $ip;
$netmask = 32;
}
- return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask);
+ return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask);
}
/**
@@ -100,6 +107,11 @@ public static function checkIp4($requestIp, $ip)
*/
public static function checkIp6($requestIp, $ip)
{
+ $cacheKey = $requestIp.'-'.$ip;
+ if (isset(self::$checkedIps[$cacheKey])) {
+ return self::$checkedIps[$cacheKey];
+ }
+
if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) {
throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".');
}
@@ -108,7 +120,7 @@ public static function checkIp6($requestIp, $ip)
list($address, $netmask) = explode('/', $ip, 2);
if ($netmask < 1 || $netmask > 128) {
- return false;
+ return self::$checkedIps[$cacheKey] = false;
}
} else {
$address = $ip;
@@ -119,7 +131,7 @@ public static function checkIp6($requestIp, $ip)
$bytesTest = unpack('n*', @inet_pton($requestIp));
if (!$bytesAddr || !$bytesTest) {
- return false;
+ return self::$checkedIps[$cacheKey] = false;
}
for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) {
@@ -127,10 +139,10 @@ public static function checkIp6($requestIp, $ip)
$left = ($left <= 16) ? $left : 16;
$mask = ~(0xffff >> $left) & 0xffff;
if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) {
- return false;
+ return self::$checkedIps[$cacheKey] = false;
}
}
- return true;
+ return self::$checkedIps[$cacheKey] = true;
}
}
diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
index 36a20550b07cf..812f5f2e4fcc0 100644
--- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
+++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
@@ -92,6 +92,10 @@ class NativeSessionStorage implements SessionStorageInterface
* upload_progress.freq, "1%"
* upload_progress.min-freq, "1"
* url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset="
+ * sid_length, "32"
+ * sid_bits_per_character, "5"
+ * trans_sid_hosts, $_SERVER['HTTP_HOST']
+ * trans_sid_tags, "a=href,area=href,frame=src,form="
*
* @param array $options Session configuration options
* @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler
@@ -340,6 +344,7 @@ public function setOptions(array $options)
'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled',
'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name',
'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags',
+ 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags',
));
foreach ($options as $key => $value) {
diff --git a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php
index 39a99e6966c22..027b2b1761334 100644
--- a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php
+++ b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php
@@ -39,7 +39,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface
*/
public function add(Response $response)
{
- if ($response->isValidateable()) {
+ if (!$response->isFresh() || !$response->isCacheable()) {
$this->cacheable = false;
} else {
$maxAge = $response->getMaxAge();
@@ -70,6 +70,9 @@ public function update(Response $response)
if ($response->isValidateable()) {
$response->setEtag(null);
$response->setLastModified(null);
+ }
+
+ if (!$response->isFresh()) {
$this->cacheable = false;
}
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index 0ffd46d11f7b1..93be7003c1b37 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -58,11 +58,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface
protected $startTime;
protected $loadClassCache;
- const VERSION = '2.7.29';
- const VERSION_ID = 20729;
+ const VERSION = '2.7.30';
+ const VERSION_ID = 20730;
const MAJOR_VERSION = 2;
const MINOR_VERSION = 7;
- const RELEASE_VERSION = 29;
+ const RELEASE_VERSION = 30;
const EXTRA_VERSION = '';
const END_OF_MAINTENANCE = '05/2018';
diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php
index f30a3b6ad94ab..5e4c322223eb3 100644
--- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php
@@ -75,4 +75,148 @@ public function testSharedMaxAgeNotSetIfNotSetInMasterRequest()
$this->assertFalse($response->headers->hasCacheControlDirective('s-maxage'));
}
+
+ public function testMasterResponseNotCacheableWhenEmbeddedResponseRequiresValidation()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $embeddedResponse = new Response();
+ $embeddedResponse->setLastModified(new \DateTime());
+ $cacheStrategy->add($embeddedResponse);
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
+ $this->assertFalse($masterResponse->isFresh());
+ }
+
+ public function testValidationOnMasterResponseIsNotPossibleWhenItContainsEmbeddedResponses()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ // This master response uses the "validation" model
+ $masterResponse = new Response();
+ $masterResponse->setLastModified(new \DateTime());
+ $masterResponse->setEtag('foo');
+
+ // Embedded response uses "expiry" model
+ $embeddedResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $cacheStrategy->add($embeddedResponse);
+
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertFalse($masterResponse->isValidateable());
+ $this->assertFalse($masterResponse->headers->has('Last-Modified'));
+ $this->assertFalse($masterResponse->headers->has('ETag'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
+ }
+
+ public function testMasterResponseWithValidationIsUnchangedWhenThereIsNoEmbeddedResponse()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setLastModified(new \DateTime());
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->isValidateable());
+ }
+
+ public function testMasterResponseWithExpirationIsUnchangedWhenThereIsNoEmbeddedResponse()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->isFresh());
+ }
+
+ public function testMasterResponseIsNotCacheableWhenEmbeddedResponseIsNotCacheable()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600); // Public, cacheable
+
+ /* This response has no validation or expiration information.
+ That makes it uncacheable, it is always stale.
+ (It does *not* make this private, though.) */
+ $embeddedResponse = new Response();
+ $this->assertFalse($embeddedResponse->isFresh()); // not fresh, as no lifetime is provided
+
+ $cacheStrategy->add($embeddedResponse);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
+ $this->assertFalse($masterResponse->isFresh());
+ }
+
+ public function testEmbeddingPrivateResponseMakesMainResponsePrivate()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600); // public, cacheable
+
+ // The embedded response might for example contain per-user data that remains valid for 60 seconds
+ $embeddedResponse = new Response();
+ $embeddedResponse->setPrivate();
+ $embeddedResponse->setMaxAge(60); // this would implicitly set "private" as well, but let's be explicit
+
+ $cacheStrategy->add($embeddedResponse);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private'));
+ // Not sure if we should pass "max-age: 60" in this case, as long as the response is private and
+ // that's the more conservative of both the master and embedded response...?
+ }
+
+ public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation()
+ {
+ /* When "expiration wins over validation" (https://symfony.com/doc/current/http_cache/validation.html)
+ * and both the main and embedded response provide s-maxage, then the more restricting value of both
+ * should be fine, regardless of whether the embedded response can be validated later on or must be
+ * completely regenerated.
+ */
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+
+ $embeddedResponse = new Response();
+ $embeddedResponse->setSharedMaxAge(60);
+ $embeddedResponse->setEtag('foo');
+
+ $cacheStrategy->add($embeddedResponse);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage'));
+ }
+
+ public function testResponseIsExpirableButNotValidateableWhenMasterResponseCombinesExpirationAndValidation()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $masterResponse->setEtag('foo');
+ $masterResponse->setLastModified(new \DateTime());
+
+ $embeddedResponse = new Response();
+ $embeddedResponse->setSharedMaxAge(60);
+
+ $cacheStrategy->add($embeddedResponse);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage'));
+ $this->assertFalse($masterResponse->isValidateable());
+ }
}
diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php
index e034aeb28a743..90689c88cb8e6 100644
--- a/src/Symfony/Component/Process/Tests/ProcessTest.php
+++ b/src/Symfony/Component/Process/Tests/ProcessTest.php
@@ -439,6 +439,9 @@ public function testExitCodeCommandFailed()
$this->assertGreaterThan(0, $process->getExitCode());
}
+ /**
+ * @group tty
+ */
public function testTTYCommand()
{
if ('\\' === DIRECTORY_SEPARATOR) {
@@ -454,6 +457,9 @@ public function testTTYCommand()
$this->assertSame(Process::STATUS_TERMINATED, $process->getStatus());
}
+ /**
+ * @group tty
+ */
public function testTTYCommandExitCode()
{
if ('\\' === DIRECTORY_SEPARATOR) {
diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
index cdb075c84621f..a6615f11e7a5e 100644
--- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
+++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
@@ -245,7 +245,7 @@ public static function handleError($type, $message, $file, $line, $context)
private static function throwInvalidArgumentException($message, $trace, $i)
{
- if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file']) {
+ if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file'] && isset($trace[$i]['args'][0])) {
$pos = strpos($message, $delim = 'must be of the type ') ?: (strpos($message, $delim = 'must be an instance of ') ?: strpos($message, $delim = 'must implement interface '));
$pos += strlen($delim);
$type = $trace[$i]['args'][0];
diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php
new file mode 100644
index 0000000000000..b6a9852715d79
--- /dev/null
+++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php
@@ -0,0 +1,31 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\PropertyAccess\Tests\Fixtures;
+
+/**
+ * @author Kévin Dunglas
+ */
+class ReturnTyped
+{
+ public function getFoos(): array
+ {
+ return 'It doesn\'t respect the return type on purpose';
+ }
+
+ public function addFoo(\DateTime $dateTime)
+ {
+ }
+
+ public function removeFoo(\DateTime $dateTime)
+ {
+ }
+}
diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
index fc434adb45a0e..bff2c728f1ca2 100644
--- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
+++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php
@@ -14,6 +14,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException;
use Symfony\Component\PropertyAccess\PropertyAccessor;
+use Symfony\Component\PropertyAccess\Tests\Fixtures\ReturnTyped;
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass;
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall;
use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet;
@@ -566,4 +567,16 @@ public function testThrowTypeErrorWithInterface()
$this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.');
}
+
+ /**
+ * @requires PHP 7
+ *
+ * @expectedException \TypeError
+ */
+ public function testDoNotDiscardReturnTypeError()
+ {
+ $object = new ReturnTyped();
+
+ $this->propertyAccessor->setValue($object, 'foos', array(new \DateTime()));
+ }
}
diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php
index 537a81e9a44b1..cdf1973df4158 100644
--- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php
+++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php
@@ -250,7 +250,7 @@ private function parseConfigs(\DOMElement $node, $path)
$condition = trim($n->textContent);
break;
default:
- throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path));
+ throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path));
}
}
diff --git a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php
index 463bc0d056809..900c59fa37392 100644
--- a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php
+++ b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php
@@ -49,7 +49,7 @@ public function match($pathinfo)
protected function handleRouteRequirements($pathinfo, $name, Route $route)
{
// expression condition
- if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) {
+ if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) {
return array(self::REQUIREMENT_MISMATCH, null);
}
diff --git a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php
index cb1a35f4d3023..9085be0424886 100644
--- a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php
+++ b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php
@@ -105,7 +105,7 @@ protected function matchCollection($pathinfo, RouteCollection $routes)
// check condition
if ($condition = $route->getCondition()) {
- if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) {
+ if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) {
$this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route);
continue;
diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php
index 9786a9b42cc60..c646723b3ab08 100644
--- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php
+++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php
@@ -207,7 +207,7 @@ protected function getAttributes(Route $route, $name, array $attributes)
protected function handleRouteRequirements($pathinfo, $name, Route $route)
{
// expression condition
- if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) {
+ if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) {
return array(self::REQUIREMENT_MISMATCH, null);
}
@@ -248,4 +248,19 @@ protected function getExpressionLanguage()
return $this->expressionLanguage;
}
+
+ /**
+ * @internal
+ */
+ protected function createRequest($pathinfo)
+ {
+ if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
+ return null;
+ }
+
+ return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), array(), array(), array(
+ 'SCRIPT_FILENAME' => $this->context->getBaseUrl(),
+ 'SCRIPT_NAME' => $this->context->getBaseUrl(),
+ ));
+ }
}
diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php
index 6d59855d2d8f3..9fd53e9814496 100644
--- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php
+++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php
@@ -337,6 +337,16 @@ public function testCondition()
$matcher->match('/foo');
}
+ public function testRequestCondition()
+ {
+ $coll = new RouteCollection();
+ $route = new Route('/foo/{bar}');
+ $route->setCondition('request.getBaseUrl() == "/sub/front.php" and request.getPathInfo() == "/foo/bar"');
+ $coll->add('foo', $route);
+ $matcher = new UrlMatcher($coll, new RequestContext('/sub/front.php'));
+ $this->assertEquals(array('bar' => 'bar', '_route' => 'foo'), $matcher->match('/foo/bar'));
+ }
+
public function testDecodeOnce()
{
$coll = new RouteCollection();
diff --git a/src/Symfony/Component/Security/Acl/Dbal/Schema.php b/src/Symfony/Component/Security/Acl/Dbal/Schema.php
index ed9327ce7b139..864d0091af3ef 100644
--- a/src/Symfony/Component/Security/Acl/Dbal/Schema.php
+++ b/src/Symfony/Component/Security/Acl/Dbal/Schema.php
@@ -21,7 +21,7 @@
*/
final class Schema extends BaseSchema
{
- protected $options;
+ private $options;
/**
* Constructor.
diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php
index 71d19adc14f2b..7bfc556bdbf25 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php
+++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php
@@ -27,7 +27,7 @@ class UsernamePasswordToken extends AbstractToken
* Constructor.
*
* @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method
- * @param string $credentials This usually is the password of the user
+ * @param mixed $credentials This usually is the password of the user
* @param string $providerKey The provider key
* @param (RoleInterface|string)[] $roles An array of roles
*
diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
index b8b6a776e9b8e..c18c2cbf09f0f 100644
--- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
+++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
@@ -144,7 +144,6 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje
{
$grant = 0;
$deny = 0;
- $abstain = 0;
foreach ($this->voters as $voter) {
$result = $voter->vote($token, $object, $attributes);
@@ -160,7 +159,6 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje
break;
default:
- ++$abstain;
break;
}
diff --git a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
index 2dc7fee49992e..5f4c146cab469 100644
--- a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
+++ b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php
@@ -39,6 +39,10 @@ public function validate($password, Constraint $constraint)
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\UserPassword');
}
+ if (null === $password || '' === $password) {
+ return;
+ }
+
$user = $this->tokenStorage->getToken()->getUser();
if (!$user instanceof UserInterface) {
diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php
index 7de83d2513369..606392de8a16c 100644
--- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php
@@ -158,7 +158,7 @@ private function attemptSwitchUser(Request $request)
*/
private function attemptExitUser(Request $request)
{
- if (false === $original = $this->getOriginalToken($this->tokenStorage->getToken())) {
+ if (null === ($currentToken = $this->tokenStorage->getToken()) || false === $original = $this->getOriginalToken($currentToken)) {
throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.');
}
diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php
index 43013520c36ba..6b6cb246c985f 100644
--- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php
+++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php
@@ -65,6 +65,17 @@ public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest()
$this->assertNull($this->tokenStorage->getToken());
}
+ /**
+ * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
+ */
+ public function testExitUserThrowsAuthenticationExceptionIfNoCurrentToken()
+ {
+ $this->tokenStorage->setToken(null);
+ $this->request->query->set('_switch_user', '_exit');
+ $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager);
+ $listener->handle($this->event);
+ }
+
/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
*/
diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
index 63bfb871e819d..5149d0dbc7d97 100644
--- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
@@ -228,7 +228,7 @@ protected function handleCircularReference($object)
return call_user_func($this->circularReferenceHandler, $object);
}
- throw new CircularReferenceException(sprintf('A circular reference has been detected (configured limit: %d).', $this->circularReferenceLimit));
+ throw new CircularReferenceException(sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d)', get_class($object), $this->circularReferenceLimit));
}
/**
diff --git a/src/Symfony/Component/Translation/DataCollectorTranslator.php b/src/Symfony/Component/Translation/DataCollectorTranslator.php
index b2049d47511ce..0243d8aa21596 100644
--- a/src/Symfony/Component/Translation/DataCollectorTranslator.php
+++ b/src/Symfony/Component/Translation/DataCollectorTranslator.php
@@ -95,7 +95,7 @@ public function getCatalogue($locale = null)
*/
public function getFallbackLocales()
{
- if ($this->translator instanceof Translator) {
+ if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
return $this->translator->getFallbackLocales();
}
diff --git a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php
index 0fd5b35ae333b..7d4db851fe23b 100644
--- a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php
+++ b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php
@@ -52,7 +52,7 @@ public function format(MessageCatalogue $messages, $domain = 'messages')
$resOffset = $this->getPosition($data);
- $data .= pack('v', count($messages))
+ $data .= pack('v', count($messages->all($domain)))
.$indexes
.$this->writePadding($data)
.$resources
@@ -63,11 +63,11 @@ public function format(MessageCatalogue $messages, $domain = 'messages')
$root = pack('V7',
$resOffset + (2 << 28), // Resource Offset + Resource Type
6, // Index length
- $keyTop, // Index keys top
- $bundleTop, // Index resources top
- $bundleTop, // Index bundle top
- count($messages), // Index max table length
- 0 // Index attributes
+ $keyTop, // Index keys top
+ $bundleTop, // Index resources top
+ $bundleTop, // Index bundle top
+ count($messages->all($domain)), // Index max table length
+ 0 // Index attributes
);
$header = pack('vC2v4C12@32',
diff --git a/src/Symfony/Component/Translation/LoggingTranslator.php b/src/Symfony/Component/Translation/LoggingTranslator.php
index b259df5e0aa49..85ab3c47f55c8 100644
--- a/src/Symfony/Component/Translation/LoggingTranslator.php
+++ b/src/Symfony/Component/Translation/LoggingTranslator.php
@@ -95,7 +95,7 @@ public function getCatalogue($locale = null)
*/
public function getFallbackLocales()
{
- if ($this->translator instanceof Translator) {
+ if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) {
return $this->translator->getFallbackLocales();
}
diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php
index fb1f1f3ef7c75..34466c7cb3251 100644
--- a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php
+++ b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php
@@ -29,6 +29,10 @@ abstract class AbstractComparison extends Constraint
*/
public function __construct($options = null)
{
+ if (null === $options) {
+ $options = array();
+ }
+
if (is_array($options) && !isset($options['value'])) {
throw new ConstraintDefinitionException(sprintf(
'The %s constraint requires the "value" option to be set.',
diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php
index 5cb126d8fe2fe..26246fe6d2aad 100644
--- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php
+++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php
@@ -48,7 +48,7 @@ public function validate($value, Constraint $constraint)
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Url');
}
- if (null === $value) {
+ if (null === $value || '' === $value) {
return;
}
diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf
index b50ecbc63a1b5..e28ea54b4512c 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf
@@ -76,7 +76,7 @@
This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less.
- Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères.
+ Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractères.This value should be {{ limit }} or more.
@@ -84,7 +84,7 @@
This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.
- Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères.
+ Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractères.This value should not be blank.
@@ -180,7 +180,7 @@
This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters.
- Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères.
+ Cette chaîne doit avoir exactement {{ limit }} caractère.|Cette chaîne doit avoir exactement {{ limit }} caractères.The file was only partially uploaded.
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php
index 9c8ce50fc3dd1..8843e6077f6d0 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php
@@ -68,14 +68,21 @@ protected static function addPhp5Dot5Comparisons(array $comparisons)
return $result;
}
+ public function provideInvalidConstraintOptions()
+ {
+ return array(
+ array(null),
+ array(array()),
+ );
+ }
+
/**
+ * @dataProvider provideInvalidConstraintOptions
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
*/
- public function testThrowsConstraintExceptionIfNoValueOrProperty()
+ public function testThrowsConstraintExceptionIfNoValueOrProperty($options)
{
- $comparison = $this->createConstraint(array());
-
- $this->validator->validate('some value', $comparison);
+ $this->createConstraint($options);
}
/**
@@ -169,9 +176,9 @@ public function provideAllInvalidComparisons()
abstract public function provideInvalidComparisons();
/**
- * @param array $options Options for the constraint
+ * @param array|null $options Options for the constraint
*
* @return Constraint
*/
- abstract protected function createConstraint(array $options);
+ abstract protected function createConstraint(array $options = null);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php
index c20db1550ba27..b396601396429 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new EqualToValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new EqualTo($options);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php
index 41708f65c966e..923c7e61a08aa 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new GreaterThanOrEqualValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new GreaterThanOrEqual($options);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php
index 85a2b1dad18d5..094949d97dfb1 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new GreaterThanValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new GreaterThan($options);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php
index 0b6a4e411af9f..d7db609e17499 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new IdenticalToValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new IdenticalTo($options);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php
index 75181355109ff..8f1666ea81572 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new LessThanOrEqualValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new LessThanOrEqual($options);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php
index d555870c120b1..6d216e31644b9 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new LessThanValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new LessThan($options);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php
index bc2c348efade0..c969e2a2af099 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new NotEqualToValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new NotEqualTo($options);
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php
index 43149847b9c5a..3aed5b7bf60b8 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php
@@ -30,7 +30,7 @@ protected function createValidator()
return new NotIdenticalToValidator();
}
- protected function createConstraint(array $options)
+ protected function createConstraint(array $options = null)
{
return new NotIdenticalTo($options);
}
diff --git a/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php b/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php
index 903641f69c636..d70c09ac4da62 100644
--- a/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php
@@ -45,7 +45,7 @@ public static function castStream($stream, array $a, Stub $stub, $isNested)
public static function castStreamContext($stream, array $a, Stub $stub, $isNested)
{
- return stream_context_get_params($stream);
+ return @stream_context_get_params($stream) ?: $a;
}
public static function castGd($gd, array $a, Stub $stub, $isNested)
diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php
index b0b57e3cda598..d50419f624394 100644
--- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php
@@ -86,7 +86,7 @@ public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $s
$storage = array();
unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967
- foreach ($c as $obj) {
+ foreach (clone $c as $obj) {
$storage[spl_object_hash($obj)] = array(
'object' => $obj,
'info' => $c->getInfo(),
diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php
index 59ba119e42914..822736abd5561 100644
--- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php
+++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php
@@ -125,9 +125,9 @@ public function dumpScalar(Cursor $cursor, $type, $value)
$style = 'num';
switch (true) {
- case INF === $value: $value = 'INF'; break;
+ case INF === $value: $value = 'INF'; break;
case -INF === $value: $value = '-INF'; break;
- case is_nan($value): $value = 'NAN'; break;
+ case is_nan($value): $value = 'NAN'; break;
default:
$value = (string) $value;
if (false === strpos($value, $this->decimalPoint)) {