diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index cb9b8a69c1638..1bad363eca810 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,6 +1,6 @@
| Q | A
| ------------- | ---
-| Branch? | 3.4 or master / 2.7, 2.8, 3.2 or 3.3
+| Branch? | 3.4 or master / 2.7, 2.8 or 3.3
| Bug fix? | yes/no
| New feature? | yes/no
| BC breaks? | yes/no
diff --git a/.travis.yml b/.travis.yml
index af674057da4b8..b7ce58bd8ffbb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -51,15 +51,38 @@ before_install:
export PHPUNIT_X="$PHPUNIT --exclude-group tty,benchmark,intl-data"
export COMPOSER_UP='composer update --no-progress --no-suggest --ansi'
+ nanoseconds() {
+ local cmd="date"
+ local format="+%s%N"
+ local os=$(uname)
+ if hash gdate > /dev/null 2>&1; then
+ cmd="gdate"
+ elif [[ "$os" = Darwin ]]; then
+ format="+%s000000000"
+ fi
+ $cmd -u $format
+ }
+ export -f nanoseconds
+
# tfold is a helper to create folded reports
tfold () {
- title=$1
- fold=$(echo $title | sed -r 's/[^-_A-Za-z\d]+/./g')
+ local title=$1
+ local fold=$(echo $title | sed -r 's/[^-_A-Za-z0-9]+/./g')
shift
- echo -e "travis_fold:start:$fold\\n\\e[1;34m$title\\e[0m"
- bash -xc "$*" 2>&1 &&
+ local id=$(printf %08x $(( RANDOM * RANDOM )))
+ local start=$(nanoseconds)
+ echo -e "travis_fold:start:$fold"
+ echo -e "travis_time:start:$id"
+ echo -e "\\e[1;34m$title\\e[0m"
+
+ bash -xc "$*" 2>&1
+ local ok=$?
+ local end=$(nanoseconds)
+ echo -e "\\ntravis_time:end:$id:start=$start,finish=$end,duration=$(($end-$start))"
+ (exit $ok) &&
echo -e "\\e[32mOK\\e[0m $title\\n\\ntravis_fold:end:$fold" ||
- ( echo -e "\\e[41mKO\\e[0m $title\\n" && exit 1 )
+ echo -e "\\e[41mKO\\e[0m $title\\n"
+ (exit $ok)
}
export -f tfold
diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md
index 335dfd82e4186..d08766327bc5e 100644
--- a/CHANGELOG-2.7.md
+++ b/CHANGELOG-2.7.md
@@ -7,6 +7,17 @@ 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.33 (2017-08-01)
+
+ * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha)
+ * bug #23684 [Debug] Missing escape in debug output (c960657)
+ * bug #23662 [VarDumper] Adapt to php 7.2 changes (nicolas-grekas)
+ * bug #23649 [Form][TwigBridge] Don't render _method in form_rest() for a child form (fmarchalemisys)
+ * bug #23619 [Validator] Fix IbanValidator for ukrainian IBANs (paroe)
+ * bug #23238 [Security] ensure the 'route' index is set before attempting to use it (gsdevme)
+ * bug #23580 Fix login redirect when referer contains a query string (fabpot)
+ * bug #23574 [VarDumper] Move locale sniffing to dump() time (nicolas-grekas)
+
* 2.7.32 (2017-07-17)
* security #23507 [Security] validate empty passwords again (xabbuh)
diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md
index 5fdc52f111daa..abb1235519a77 100644
--- a/CHANGELOG-2.8.md
+++ b/CHANGELOG-2.8.md
@@ -7,6 +7,19 @@ in 2.8 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.8.0...v2.8.1
+* 2.8.27 (2017-08-28)
+
+ * bug #23989 [Debug] Remove false-positive check in DebugClassLoader (nicolas-grekas)
+ * bug #23982 [VarDumper] Strengthen dumped JS (nicolas-grekas)
+ * bug #23925 [Validator] Fix use of GroupSequenceProvider in child classes (linniksa)
+ * bug #23945 [Validator] Fix Greek translation (azhurb)
+ * bug #23909 [Console] Initialize lazily to render exceptions properly (nicolas-grekas)
+ * bug #23856 [DI] Fix dumping abstract with YamlDumper (nicolas-grekas)
+ * bug #23752 Ignore memcached missing key error on session destroy (jderusse)
+ * bug #23658 [HttpFoundation] Generate safe fallback filename for wrongly encoded filename (xelaris)
+ * bug #23783 Avoid infinite loops when profiler data is malformed (javiereguiluz)
+ * bug #23729 [Bridge\ProxyManager] Dont call __destruct() on non-instantiated services (nicolas-grekas)
+
* 2.8.26 (2017-08-01)
* bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha)
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 47a6cf9986dcf..1b059f5012cb7 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)
- Maxime Steinhausser (ogizanagi)
- - Abdellatif Ait boudad (aitboudad)
- Robin Chalas (chalas_r)
+ - Abdellatif Ait boudad (aitboudad)
+ - Grégoire Pineau (lyrixx)
- Romain Neutron (romain)
- Pascal Borreli (pborreli)
- - Grégoire Pineau (lyrixx)
- Wouter De Jong (wouterj)
- Joseph Bielawski (stloyd)
- Karma Dordrak (drak)
@@ -34,8 +34,8 @@ Symfony is the result of the work of many people who made the code better
- Jean-François Simon (jfsimon)
- Benjamin Eberlei (beberlei)
- Igor Wiedler (igorw)
- - Eriksen Costa (eriksencosta)
- Roland Franssen (ro0)
+ - Eriksen Costa (eriksencosta)
- Jules Pietri (heah)
- Sarah Khalil (saro0h)
- Guilhem Niot (energetick)
@@ -66,6 +66,7 @@ Symfony is the result of the work of many people who made the code better
- Eric Clemmons (ericclemmons)
- Charles Sarrazin (csarrazi)
- Christian Raue
+ - Konstantin Myakshin (koc)
- Arnout Boks (aboks)
- Deni
- Henrik Westphal (snc)
@@ -73,7 +74,7 @@ Symfony is the result of the work of many people who made the code better
- Jáchym Toušek (enumag)
- Titouan Galopin (tgalopin)
- Douglas Greenshields (shieldo)
- - Konstantin Myakshin (koc)
+ - Dany Maillard (maidmaid)
- Lee McDermott
- Brandon Turner
- Luis Cordova (cordoval)
@@ -89,23 +90,22 @@ Symfony is the result of the work of many people who made the code better
- Fran Moreno (franmomu)
- Antoine Hérault (herzult)
- Paráda József (paradajozsef)
+ - Issei Murasawa (issei_m)
- Arnaud Le Blanc (arnaud-lb)
- Maxime STEINHAUSSER
- Alexander M. Turek (derrabus)
- Michal Piotrowski (eventhorizon)
- - Dany Maillard (maidmaid)
- - Issei Murasawa (issei_m)
- Tim Nagel (merk)
+ - Yonel Ceruto González (yonelceruto)
- Brice BERNARD (brikou)
- Baptiste Clavié (talus)
- Vladimir Reznichenko (kalessil)
- marc.weistroff
- - Yonel Ceruto González (yonelceruto)
- lenar
+ - Tobias Nyholm (tobias)
- Włodzimierz Gajda (gajdaw)
- Alexander Schwenn (xelaris)
- Jacob Dreesen (jdreesen)
- - Tobias Nyholm (tobias)
- Florian Voutzinos (florianv)
- Colin Frei
- Adrien Brault (adrienbrault)
@@ -132,13 +132,13 @@ Symfony is the result of the work of many people who made the code better
- Daniel Gomes (danielcsgomes)
- Hidenori Goto (hidenorigoto)
- Guilherme Blanco (guilhermeblanco)
+ - David Maicher (dmaicher)
- Pablo Godel (pgodel)
- Jérémie Augustin (jaugustin)
- Andréia Bohner (andreia)
- Rafael Dohms (rdohms)
- Arnaud Kleinpeter (nanocom)
- jwdeitch
- - David Maicher (dmaicher)
- Mikael Pajunen
- Joel Wurtz (brouznouf)
- Jérôme Vasseur (jvasseur)
@@ -175,6 +175,7 @@ Symfony is the result of the work of many people who made the code better
- Dennis Benkert (denderello)
- Benjamin Dulau (dbenjamin)
- Mathieu Lemoine (lemoinem)
+ - Christian Schmidt
- Andreas Hucks (meandmymonkey)
- Noel Guilbert (noel)
- Stepan Anchugov (kix)
@@ -200,7 +201,6 @@ Symfony is the result of the work of many people who made the code better
- John Kary (johnkary)
- Justin Hileman (bobthecow)
- Blanchon Vincent (blanchonvincent)
- - Christian Schmidt
- Michele Orselli (orso)
- Tom Van Looy (tvlooy)
- Sven Paulus (subsven)
@@ -236,6 +236,7 @@ Symfony is the result of the work of many people who made the code better
- Katsuhiro OGAWA
- Patrick McDougle (patrick-mcdougle)
- Alif Rachmawadi
+ - Alessandro Chitolina
- Kristen Gilden (kgilden)
- Pierre-Yves LEBECQ (pylebecq)
- Jordan Samouh (jordansamouh)
@@ -261,6 +262,8 @@ Symfony is the result of the work of many people who made the code better
- Pavel Batanov (scaytrase)
- Nikita Konstantinov
- Wodor Wodorski
+ - Rob Frawley 2nd (robfrawley)
+ - Gregor Harlan (gharlan)
- Thomas Lallement (raziel057)
- Giorgio Premi
- Matthieu Napoli (mnapoli)
@@ -276,7 +279,6 @@ Symfony is the result of the work of many people who made the code better
- Marc Weistroff (futurecat)
- Christian Schmidt
- Hidde Wieringa (hiddewie)
- - Alessandro Chitolina
- Chad Sikorra (chadsikorra)
- Chris Smith (cs278)
- Florian Klein (docteurklein)
@@ -313,7 +315,6 @@ Symfony is the result of the work of many people who made the code better
- Thierry Thuon (lepiaf)
- Ricard Clau (ricardclau)
- Mark Challoner (markchalloner)
- - Gregor Harlan (gharlan)
- Gennady Telegin (gtelegin)
- Ben Davies (bendavies)
- Erin Millard
@@ -322,7 +323,6 @@ Symfony is the result of the work of many people who made the code better
- Magnus Nordlander (magnusnordlander)
- alquerci
- Francesco Levorato
- - Rob Frawley 2nd (robfrawley)
- Vitaliy Zakharov (zakharovvi)
- Tobias Sjösten (tobiassjosten)
- Gyula Sallai (salla)
@@ -339,6 +339,7 @@ Symfony is the result of the work of many people who made the code better
- Thomas Calvet (fancyweb)
- Niels Keurentjes (curry684)
- JhonnyL
+ - David Badura (davidbadura)
- hossein zolfi (ocean)
- Clément Gautier (clementgautier)
- Eduardo Gulias (egulias)
@@ -428,7 +429,6 @@ Symfony is the result of the work of many people who made the code better
- Christian Wahler
- Gintautas Miselis
- Rob Bast
- - David Badura (davidbadura)
- Zander Baldwin
- Adam Harvey
- Maxime Veber (nek-)
@@ -543,6 +543,7 @@ Symfony is the result of the work of many people who made the code better
- Max Rath (drak3)
- Stéphane Escandell (sescandell)
- Konstantin S. M. Möllers (ksmmoellers)
+ - James Johnston
- Sinan Eldem
- Alexandre Dupuy (satchette)
- Andre Rømcke (andrerom)
@@ -591,6 +592,7 @@ Symfony is the result of the work of many people who made the code better
- Ulumuddin Yunus (joenoez)
- Luc Vieillescazes (iamluc)
- Johann Saunier (prophet777)
+ - Valentin Udaltsov (vudaltsov)
- Michael Devery (mickadoo)
- Antoine Corcy
- Artur Eshenbrener
@@ -909,6 +911,7 @@ Symfony is the result of the work of many people who made the code better
- Alex Demchenko (pilot)
- Tadas Gliaubicas (tadcka)
- Benoit Garret
+ - Jakub Sacha
- DerManoMann
- Olaf Klischat
- orlovv
@@ -1173,6 +1176,7 @@ Symfony is the result of the work of many people who made the code better
- Malte Wunsch
- wusuopu
- povilas
+ - Gavin Staniforth
- Alessandro Tagliapietra (alex88)
- Biji (biji)
- Gunnar Lium (gunnarlium)
@@ -1234,6 +1238,7 @@ Symfony is the result of the work of many people who made the code better
- flack
- izzyp
- František Bereň
+ - Mike Francis
- Christoph Nissle (derstoffel)
- Ionel Scutelnicu (ionelscutelnicu)
- Nicolas Tallefourtané (nicolab)
@@ -1244,6 +1249,7 @@ Symfony is the result of the work of many people who made the code better
- jjanvier
- Julius Beckmann
- Romain Dorgueil
+ - Christopher Parotat
- Grayson Koonce (breerly)
- Fabien LUCAS (flucas2)
- Indra Gunawan (indragunawan)
@@ -1535,11 +1541,13 @@ Symfony is the result of the work of many people who made the code better
- Ladislav Tánczos
- Brian Freytag
- Skorney
+ - fmarchalemisys
- mieszko4
- Steve Preston
- Neophy7e
- bokonet
- Arrilot
+ - Shaun Simmons
- Markus Staab
- Pierre-Louis LAUNAY
- djama
@@ -1568,6 +1576,7 @@ Symfony is the result of the work of many people who made the code better
- Penny Leach
- Richard Trebichavský
- g123456789l
+ - Jonathan Vollebregt
- oscartv
- DanSync
- Peter Zwosta
@@ -1680,7 +1689,6 @@ Symfony is the result of the work of many people who made the code better
- Moritz Kraft (userfriendly)
- Víctor Mateo (victormateo)
- Vincent (vincent1870)
- - Valentin Udaltsov (vudaltsov)
- Eugene Babushkin (warl)
- Wouter Sioen (wouter_sioen)
- Xavier Amado (xamado)
@@ -1702,6 +1710,7 @@ Symfony is the result of the work of many people who made the code better
- Sergey Fedotov
- Michael
- fh-github@fholzhauer.de
+ - AbdElKader Bouadjadja
- Jan Emrich
- Mark Topper
- Xavier REN
diff --git a/UPGRADE-2.8.md b/UPGRADE-2.8.md
index 1d299af3e63a4..64a31dde75600 100644
--- a/UPGRADE-2.8.md
+++ b/UPGRADE-2.8.md
@@ -547,6 +547,95 @@ Security
* The `VoterInterface::supportsClass` and `supportsAttribute` methods were
deprecated and will be removed from the interface in 3.0.
+ * The `key` setting of `anonymous`, `remember_me` and `http_digest` is
+ deprecated, and will be removed in 3.0. Use `secret` instead.
+
+ Before:
+
+ ```yaml
+ security:
+ # ...
+ firewalls:
+ default:
+ # ...
+ anonymous: { key: "%secret%" }
+ remember_me:
+ key: "%secret%"
+ http_digest:
+ key: "%secret%"
+ ```
+
+ ```xml
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+ ```php
+ // ...
+ $container->loadFromExtension('security', array(
+ // ...
+ 'firewalls' => array(
+ // ...
+ 'anonymous' => array('key' => '%secret%'),
+ 'remember_me' => array('key' => '%secret%'),
+ 'http_digest' => array('key' => '%secret%'),
+ ),
+ ));
+ ```
+
+ After:
+
+ ```yaml
+ security:
+ # ...
+ firewalls:
+ default:
+ # ...
+ anonymous: { secret: "%secret%" }
+ remember_me:
+ secret: "%secret%"
+ http_digest:
+ secret: "%secret%"
+ ```
+
+ ```xml
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+ ```php
+ // ...
+ $container->loadFromExtension('security', array(
+ // ...
+ 'firewalls' => array(
+ // ...
+ 'anonymous' => array('secret' => '%secret%'),
+ 'remember_me' => array('secret' => '%secret%'),
+ 'http_digest' => array('secret' => '%secret%'),
+ ),
+ ));
+ ```
+
* The `intention` option is deprecated for all the authentication listeners,
and will be removed in 3.0. Use the `csrf_token_id` option instead.
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php
new file mode 100644
index 0000000000000..3298b84d46278
--- /dev/null
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.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\Bridge\ProxyManager\LazyProxy\Instantiator;
+
+use ProxyManager\Factory\LazyLoadingValueHolderFactory as BaseFactory;
+use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\LazyLoadingValueHolderGenerator;
+
+/**
+ * @internal
+ */
+class LazyLoadingValueHolderFactoryV1 extends BaseFactory
+{
+ private $generatorV1;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getGenerator()
+ {
+ return $this->generatorV1 ?: $this->generatorV1 = new LazyLoadingValueHolderGenerator();
+ }
+}
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php
new file mode 100644
index 0000000000000..f41fc20b5d523
--- /dev/null
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php
@@ -0,0 +1,32 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator;
+
+use ProxyManager\ProxyGenerator\ProxyGeneratorInterface;
+use ProxyManager\Factory\LazyLoadingValueHolderFactory as BaseFactory;
+use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\LazyLoadingValueHolderGenerator;
+
+/**
+ * @internal
+ */
+class LazyLoadingValueHolderFactoryV2 extends BaseFactory
+{
+ private $generator;
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getGenerator(): ProxyGeneratorInterface
+ {
+ return $this->generator ?: $this->generator = new LazyLoadingValueHolderGenerator();
+ }
+}
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php
index 0101026794c7c..33fc49e1012d9 100644
--- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php
@@ -36,7 +36,11 @@ public function __construct()
$config = new Configuration();
$config->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
- $this->factory = new LazyLoadingValueHolderFactory($config);
+ if (method_exists('ProxyManager\Version', 'getVersion')) {
+ $this->factory = new LazyLoadingValueHolderFactoryV2($config);
+ } else {
+ $this->factory = new LazyLoadingValueHolderFactoryV1($config);
+ }
}
/**
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php
new file mode 100644
index 0000000000000..1d9432f622b41
--- /dev/null
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php
@@ -0,0 +1,41 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper;
+
+use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator as BaseGenerator;
+use Zend\Code\Generator\ClassGenerator;
+
+/**
+ * @internal
+ */
+class LazyLoadingValueHolderGenerator extends BaseGenerator
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function generate(\ReflectionClass $originalClass, ClassGenerator $classGenerator)
+ {
+ parent::generate($originalClass, $classGenerator);
+
+ if ($classGenerator->hasMethod('__destruct')) {
+ $destructor = $classGenerator->getMethod('__destruct');
+ $body = $destructor->getBody();
+ $newBody = preg_replace('/^(\$this->initializer[a-zA-Z0-9]++) && .*;\n\nreturn (\$this->valueHolder)/', '$1 || $2', $body);
+
+ if ($body === $newBody) {
+ throw new \UnexpectedValueException(sprintf('Unexpected lazy-proxy format generated for method %s::__destruct()', $originalClass->name));
+ }
+
+ $destructor->setBody($newBody);
+ }
+ }
+}
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php
index 417d94e47215e..3db1ac7ebae75 100644
--- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php
@@ -13,7 +13,6 @@
use ProxyManager\Generator\ClassGenerator;
use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy;
-use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php
index b634a69488a34..858e9d76b64c9 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php
@@ -39,6 +39,9 @@ public function testCreateProxyServiceWithRuntimeInstantiator()
/* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */
$foo1 = $builder->get('foo1');
+ $foo1->__destruct();
+ $this->assertSame(0, $foo1::$destructorCount);
+
$this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls');
$this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1);
$this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1);
@@ -50,5 +53,8 @@ public function testCreateProxyServiceWithRuntimeInstantiator()
$this->assertTrue($foo1->isProxyInitialized());
$this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1->getWrappedValueHolderValue());
$this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue());
+
+ $foo1->__destruct();
+ $this->assertSame(1, $foo1::$destructorCount);
}
}
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php
index 16c898a370845..8ffc5be9af40a 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php
@@ -2,6 +2,8 @@
class ProxyManagerBridgeFooClass
{
+ public static $destructorCount = 0;
+
public $foo;
public $moo;
@@ -38,4 +40,9 @@ public function setBar($value = null)
{
$this->bar = $value;
}
+
+ public function __destruct()
+ {
+ ++self::$destructorCount;
+ }
}
diff --git a/src/Symfony/Bundle/DebugBundle/DebugBundle.php b/src/Symfony/Bundle/DebugBundle/DebugBundle.php
index 335ec5abd2541..b00c06af78289 100644
--- a/src/Symfony/Bundle/DebugBundle/DebugBundle.php
+++ b/src/Symfony/Bundle/DebugBundle/DebugBundle.php
@@ -27,8 +27,10 @@ public function boot()
$container = $this->container;
// This code is here to lazy load the dump stack. This default
- // configuration for CLI mode is overridden in HTTP mode on
- // 'kernel.request' event
+ // configuration is overridden in CLI mode on 'console.command' event.
+ // The dump data collector is used by default, so dump output is sent to
+ // the WDT. In a CLI context, if dump is used too soon, the data collector
+ // will buffer it, and release it at the end of the script.
VarDumper::setHandler(function ($var) use ($container) {
$dumper = $container->get('data_collector.dump');
$cloner = $container->get('var_dumper.cloner');
diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php
index 6dfa571a31822..f110f815478cf 100644
--- a/src/Symfony/Component/Console/Application.php
+++ b/src/Symfony/Component/Console/Application.php
@@ -75,6 +75,7 @@ class Application
private $dispatcher;
private $terminalDimensions;
private $defaultCommand;
+ private $initialized;
/**
* Constructor.
@@ -87,12 +88,6 @@ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
$this->name = $name;
$this->version = $version;
$this->defaultCommand = 'list';
- $this->helperSet = $this->getDefaultHelperSet();
- $this->definition = $this->getDefaultInputDefinition();
-
- foreach ($this->getDefaultCommands() as $command) {
- $this->add($command);
- }
}
public function setDispatcher(EventDispatcherInterface $dispatcher)
@@ -192,10 +187,11 @@ public function doRun(InputInterface $input, OutputInterface $output)
if (!$name) {
$name = $this->defaultCommand;
- $this->definition->setArguments(array_merge(
- $this->definition->getArguments(),
+ $definition = $this->getDefinition();
+ $definition->setArguments(array_merge(
+ $definition->getArguments(),
array(
- 'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name),
+ 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name),
)
));
}
@@ -228,6 +224,10 @@ public function setHelperSet(HelperSet $helperSet)
*/
public function getHelperSet()
{
+ if (!$this->helperSet) {
+ $this->helperSet = $this->getDefaultHelperSet();
+ }
+
return $this->helperSet;
}
@@ -248,6 +248,10 @@ public function setDefinition(InputDefinition $definition)
*/
public function getDefinition()
{
+ if (!$this->definition) {
+ $this->definition = $this->getDefaultInputDefinition();
+ }
+
return $this->definition;
}
@@ -377,6 +381,8 @@ public function addCommands(array $commands)
*/
public function add(Command $command)
{
+ $this->init();
+
$command->setApplication($this);
if (!$command->isEnabled()) {
@@ -409,6 +415,8 @@ public function add(Command $command)
*/
public function get($name)
{
+ $this->init();
+
if (!isset($this->commands[$name])) {
throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
}
@@ -436,6 +444,8 @@ public function get($name)
*/
public function has($name)
{
+ $this->init();
+
return isset($this->commands[$name]);
}
@@ -513,6 +523,8 @@ public function findNamespace($namespace)
*/
public function find($name)
{
+ $this->init();
+
$allCommands = array_keys($this->commands);
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
$commands = preg_grep('{^'.$expr.'}', $allCommands);
@@ -568,6 +580,8 @@ public function find($name)
*/
public function all($namespace = null)
{
+ $this->init();
+
if (null === $namespace) {
return $this->commands;
}
@@ -1157,4 +1171,16 @@ private function extractAllNamespaces($name)
return $namespaces;
}
+
+ private function init()
+ {
+ if ($this->initialized) {
+ return;
+ }
+ $this->initialized = true;
+
+ foreach ($this->getDefaultCommands() as $command) {
+ $this->add($command);
+ }
+ }
}
diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php
index a6a5cd7af09d3..8b6b4b7f2e750 100644
--- a/src/Symfony/Component/Debug/DebugClassLoader.php
+++ b/src/Symfony/Component/Debug/DebugClassLoader.php
@@ -26,6 +26,7 @@ class DebugClassLoader
{
private $classLoader;
private $isFinder;
+ private $loaded = array();
private $wasFinder;
private static $caseCheck;
private static $deprecated = array();
@@ -164,9 +165,10 @@ public function loadClass($class)
ErrorHandler::stackErrors();
try {
- if ($this->isFinder) {
+ if ($this->isFinder && !isset($this->loaded[$class])) {
+ $this->loaded[$class] = true;
if ($file = $this->classLoader[0]->findFile($class)) {
- require_once $file;
+ require $file;
}
} else {
call_user_func($this->classLoader, $class);
diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php
index 196b92c884598..c82c07543a404 100644
--- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php
+++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php
@@ -59,6 +59,23 @@ public function testIdempotence()
$this->fail('DebugClassLoader did not register');
}
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage boo
+ */
+ public function testThrowingClass()
+ {
+ try {
+ class_exists(__NAMESPACE__.'\Fixtures\Throwing');
+ $this->fail('Exception expected');
+ } catch (\Exception $e) {
+ $this->assertSame('boo', $e->getMessage());
+ }
+
+ // the second call also should throw
+ class_exists(__NAMESPACE__.'\Fixtures\Throwing');
+ }
+
public function testUnsilencing()
{
if (\PHP_VERSION_ID >= 70000) {
@@ -128,6 +145,7 @@ class ChildTestingStacking extends TestingStacking { function foo($bar) {} }
/**
* @expectedException \RuntimeException
+ * @expectedExceptionMessage Case mismatch between loaded and declared class names
*/
public function testNameCaseMismatch()
{
@@ -149,6 +167,7 @@ class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true);
/**
* @expectedException \RuntimeException
+ * @expectedExceptionMessage Case mismatch between loaded and declared class names
*/
public function testPsr4CaseMismatch()
{
diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php
new file mode 100644
index 0000000000000..21e0aba17d358
--- /dev/null
+++ b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php
@@ -0,0 +1,3 @@
+properties = $properties;
@@ -272,11 +279,24 @@ public function setProperties(array $properties)
return $this;
}
+ /**
+ * Gets the properties to define when creating the service.
+ *
+ * @return array
+ */
public function getProperties()
{
return $this->properties;
}
+ /**
+ * Sets a specific property.
+ *
+ * @param string $name
+ * @param mixed $value
+ *
+ * @return $this
+ */
public function setProperty($name, $value)
{
$this->properties[$name] = $value;
@@ -299,7 +319,7 @@ public function addArgument($argument)
}
/**
- * Sets a specific argument.
+ * Replaces a specific argument.
*
* @param int $index
* @param mixed $argument
@@ -854,7 +874,7 @@ public function isAutowired()
}
/**
- * Sets autowired.
+ * Enables/disables autowiring.
*
* @param bool $autowired
*
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
index f966b823486fd..9e59ba32e28c6 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
@@ -120,6 +120,10 @@ private function addService($id, $definition)
$code .= sprintf(" factory_class: %s\n", $this->dumper->dump($definition->getFactoryClass(false)));
}
+ if ($definition->isAbstract()) {
+ $code .= " abstract: true\n";
+ }
+
if ($definition->isLazy()) {
$code .= " lazy: true\n";
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php
index 43734f7216df7..e61eca1d0151d 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php
@@ -12,8 +12,10 @@
namespace Symfony\Component\DependencyInjection\Tests\Dumper;
use PHPUnit\Framework\TestCase;
+use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\Yaml\Yaml;
class YamlDumperTest extends TestCase
@@ -84,6 +86,16 @@ public function testDumpAutowireData()
$this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services24.yml', $dumper->dump());
}
+ public function testDumpLoad()
+ {
+ $container = new ContainerBuilder();
+ $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
+ $loader->load('services_dump_load.yml');
+
+ $dumper = new YamlDumper($container);
+ $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_dump_load.yml', $dumper->dump());
+ }
+
private function assertEqualYamlStructure($yaml, $expected, $message = '')
{
$this->assertEquals(Yaml::parse($expected), Yaml::parse($yaml), $message);
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml
new file mode 100644
index 0000000000000..bcf8f31b36115
--- /dev/null
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml
@@ -0,0 +1,4 @@
+
+services:
+ foo:
+ abstract: true
diff --git a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php
index 827570fb60e48..f002627ef5942 100644
--- a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php
+++ b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php
@@ -373,7 +373,7 @@ public function testText()
public function testHtml()
{
$this->assertEquals('', $this->createTestCrawler()->filterXPath('//a[5]')->html());
- $this->assertEquals('', trim($this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html()));
+ $this->assertEquals('', trim(preg_replace('~>\s+<~', '><', $this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html())));
try {
$this->createTestCrawler()->filterXPath('//ol')->html();
diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php
index 0314621907356..177b708e8f054 100644
--- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php
+++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php
@@ -150,7 +150,7 @@ public function setAutoEtag()
* Sets the Content-Disposition header with the given filename.
*
* @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT
- * @param string $filename Optionally use this filename instead of the real name of the file
+ * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file
* @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename
*
* @return $this
@@ -162,7 +162,7 @@ public function setContentDisposition($disposition, $filename = '', $filenameFal
}
if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || false !== strpos($filename, '%'))) {
- $encoding = mb_detect_encoding($filename, null, true);
+ $encoding = mb_detect_encoding($filename, null, true) ?: '8bit';
for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) {
$char = mb_substr($filename, $i, 1, $encoding);
diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php
index 962a3878d9767..4e490a05d4ce0 100644
--- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php
+++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php
@@ -95,7 +95,9 @@ public function write($sessionId, $data)
*/
public function destroy($sessionId)
{
- return $this->memcache->delete($this->prefix.$sessionId);
+ $this->memcache->delete($this->prefix.$sessionId);
+
+ return true;
}
/**
diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php
index 76b08e2db944c..67a49ad6f5e2a 100644
--- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php
+++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php
@@ -101,7 +101,9 @@ public function write($sessionId, $data)
*/
public function destroy($sessionId)
{
- return $this->memcached->delete($this->prefix.$sessionId);
+ $result = $this->memcached->delete($this->prefix.$sessionId);
+
+ return $result || $this->memcached->getResultCode() == \Memcached::RES_NOTFOUND;
}
/**
diff --git a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php
index e4607201a2151..e41a2372b9df8 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php
@@ -68,6 +68,17 @@ public function testSetContentDispositionGeneratesSafeFallbackFilename()
$this->assertSame('attachment; filename="f__.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html', $response->headers->get('Content-Disposition'));
}
+ public function testSetContentDispositionGeneratesSafeFallbackFilenameForWronglyEncodedFilename()
+ {
+ $response = new BinaryFileResponse(__FILE__);
+
+ $iso88591EncodedFilename = utf8_decode('föö.html');
+ $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $iso88591EncodedFilename);
+
+ // the parameter filename* is invalid in this case (rawurldecode('f%F6%F6') does not provide a UTF-8 string but an ISO-8859-1 encoded one)
+ $this->assertSame('attachment; filename="f__.html"; filename*=utf-8\'\'f%F6%F6.html', $response->headers->get('Content-Disposition'));
+ }
+
/**
* @dataProvider provideRanges
*/
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index 118d67aaec835..89aaa72cf9a35 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -59,11 +59,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface
protected $startTime;
protected $loadClassCache;
- const VERSION = '2.8.26';
- const VERSION_ID = 20826;
+ const VERSION = '2.8.27';
+ const VERSION_ID = 20827;
const MAJOR_VERSION = 2;
const MINOR_VERSION = 8;
- const RELEASE_VERSION = 26;
+ const RELEASE_VERSION = 27;
const EXTRA_VERSION = '';
const END_OF_MAINTENANCE = '11/2018';
diff --git a/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php
index 29da4abf32ccf..045058991063d 100644
--- a/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php
+++ b/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php
@@ -144,11 +144,19 @@ public function write(Profile $profile)
}
}
+ $profileToken = $profile->getToken();
+ // when there are errors in sub-requests, the parent and/or children tokens
+ // may equal the profile token, resulting in infinite loops
+ $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null;
+ $childrenToken = array_filter(array_map(function ($p) use ($profileToken) {
+ return $profileToken !== $p->getToken() ? $p->getToken() : null;
+ }, $profile->getChildren()));
+
// Store profile
$data = array(
- 'token' => $profile->getToken(),
- 'parent' => $profile->getParentToken(),
- 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
+ 'token' => $profileToken,
+ 'parent' => $parentToken,
+ 'children' => $childrenToken,
'data' => $profile->getCollectors(),
'ip' => $profile->getIp(),
'method' => $profile->getMethod(),
diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php
index dad52401daf39..a6d6285481015 100644
--- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php
@@ -13,6 +13,7 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\Config\EnvParametersResource;
use Symfony\Component\HttpKernel\Kernel;
@@ -25,6 +26,12 @@
class KernelTest extends TestCase
{
+ public static function tearDownAfterClass()
+ {
+ $fs = new Filesystem();
+ $fs->remove(__DIR__.'/Fixtures/cache');
+ }
+
public function testConstructor()
{
$env = 'test_env';
diff --git a/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php b/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php
index 84b20abf77ee8..4521b06d43936 100644
--- a/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php
+++ b/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php
@@ -32,17 +32,15 @@ public function read($path, $locale)
if (!file_exists($fileName)) {
throw new ResourceBundleNotFoundException(sprintf(
- 'The resource bundle "%s/%s.json" does not exist.',
- $path,
- $locale
+ 'The resource bundle "%s" does not exist.',
+ $fileName
));
}
if (!is_file($fileName)) {
throw new RuntimeException(sprintf(
- 'The resource bundle "%s/%s.json" is not a file.',
- $path,
- $locale
+ 'The resource bundle "%s" is not a file.',
+ $fileName
));
}
@@ -50,9 +48,8 @@ public function read($path, $locale)
if (null === $data) {
throw new RuntimeException(sprintf(
- 'The resource bundle "%s/%s.json" contains invalid JSON: %s',
- $path,
- $locale,
+ 'The resource bundle "%s" contains invalid JSON: %s',
+ $fileName,
json_last_error_msg()
));
}
diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php
index 11d09363c5a9f..4ed96cee9accb 100644
--- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php
+++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php
@@ -357,9 +357,9 @@ public function formatCurrency($value, $currency)
/**
* Format a number.
*
- * @param number $value The value to format
- * @param int $type Type of the formatting, one of the format type constants
- * Only type NumberFormatter::TYPE_DEFAULT is currently supported.
+ * @param int|float $value The value to format
+ * @param int $type Type of the formatting, one of the format type constants
+ * Only type NumberFormatter::TYPE_DEFAULT is currently supported.
*
* @return bool|string The formatted value or false on error
*
diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php
index fef4a04fb9702..307d70f9e973e 100644
--- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php
+++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php
@@ -153,6 +153,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token,
* done by having a _remember_me checkbox in your form, but
* can be configured by the "always_remember_me" and "remember_me_parameter"
* parameters under the "remember_me" firewall key
+ * D) The onAuthenticationSuccess method returns a Response object
*
* @return bool
*/
diff --git a/src/Symfony/Component/Security/Http/SecurityEvents.php b/src/Symfony/Component/Security/Http/SecurityEvents.php
index 46c8257f18e74..3bd80723d1ef5 100644
--- a/src/Symfony/Component/Security/Http/SecurityEvents.php
+++ b/src/Symfony/Component/Security/Http/SecurityEvents.php
@@ -14,8 +14,11 @@
final class SecurityEvents
{
/**
- * The INTERACTIVE_LOGIN event occurs after a user is logged in
- * interactively for authentication based on http, cookies or X509.
+ * The INTERACTIVE_LOGIN event occurs after a user has actively logged
+ * into your website. It is important to distinguish this action from
+ * non-interactive authentication methods, such as:
+ * - authentication based on your session.
+ * - authentication using a HTTP basic or HTTP digest header.
*
* The event listener method receives a
* Symfony\Component\Security\Http\Event\InteractiveLoginEvent instance.
diff --git a/src/Symfony/Component/Validator/Constraints/File.php b/src/Symfony/Component/Validator/Constraints/File.php
index 341fbaf440775..c4147f853728a 100644
--- a/src/Symfony/Component/Validator/Constraints/File.php
+++ b/src/Symfony/Component/Validator/Constraints/File.php
@@ -18,6 +18,8 @@
* @Annotation
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
*
+ * @property int $maxSize
+ *
* @author Bernhard Schussek
*/
class File extends Constraint
diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php
index f895ad40402dc..5b82cf6d5d9d6 100644
--- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php
+++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php
@@ -381,6 +381,10 @@ public function addGetterMethodConstraints($property, $method, array $constraint
*/
public function mergeConstraints(ClassMetadata $source)
{
+ if ($source->isGroupSequenceProvider()) {
+ $this->setGroupSequenceProvider(true);
+ }
+
foreach ($source->getConstraints() as $constraint) {
$this->addConstraint(clone $constraint);
}
diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf
index 4fa0d42220500..a3199bcc9d79e 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf
@@ -100,7 +100,7 @@
This value is not valid.
- Αυτή η τιμή δεν είναι έκγυρη.
+ Αυτή η τιμή δεν είναι έγκυρη.This value is not a valid time.
@@ -136,11 +136,11 @@
This is not a valid IP address.
- Αυτό δεν είναι μια έκγυρη διεύθυνση IP.
+ Αυτό δεν είναι μια έγκυρη διεύθυνση IP.This value is not a valid language.
- Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη γλώσσα.
+ Αυτή η τιμή δεν αντιστοιχεί σε μια έγκυρη γλώσσα.This value is not a valid locale.
@@ -148,7 +148,7 @@
This value is not a valid country.
- Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη χώρα.
+ Αυτή η τιμή δεν αντιστοιχεί σε μια έγκυρη χώρα.This value is already used.
diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php b/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php
new file mode 100644
index 0000000000000..be7191f9b6e1d
--- /dev/null
+++ b/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php
@@ -0,0 +1,16 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Validator\Tests\Fixtures;
+
+class GroupSequenceProviderChildEntity extends GroupSequenceProviderEntity
+{
+}
diff --git a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php
index 9a23e8cf355a0..a3f8a8c1ec8a3 100644
--- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php
+++ b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php
@@ -24,6 +24,7 @@ class ClassMetadataTest extends TestCase
const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity';
const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent';
const PROVIDERCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity';
+ const PROVIDERCHILDCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderChildEntity';
protected $metadata;
@@ -301,6 +302,17 @@ public function testGroupSequenceProvider()
$this->assertTrue($metadata->isGroupSequenceProvider());
}
+ public function testMergeConstraintsMergesGroupSequenceProvider()
+ {
+ $parent = new ClassMetadata(self::PROVIDERCLASS);
+ $parent->setGroupSequenceProvider(true);
+
+ $metadata = new ClassMetadata(self::PROVIDERCHILDCLASS);
+ $metadata->mergeConstraints($parent);
+
+ $this->assertTrue($metadata->isGroupSequenceProvider());
+ }
+
/**
* https://github.com/symfony/symfony/issues/11604.
*/
@@ -309,13 +321,3 @@ public function testGetPropertyMetadataReturnsEmptyArrayWithoutConfiguredMetadat
$this->assertCount(0, $this->metadata->getPropertyMetadata('foo'), '->getPropertyMetadata() returns an empty collection if no metadata is configured for the given property');
}
}
-
-class ParentClass
-{
- public $example = 0;
-}
-
-class ChildClass extends ParentClass
-{
- public $example = 1; // overrides parent property of same name
-}
diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
index d5a9c2c9ebc1c..b6f3f6e2de63c 100644
--- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
+++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
@@ -139,7 +139,8 @@ public function dump(Data $data, $output = null)
/**
* Dumps the current line.
*
- * @param int $depth The recursive depth in the dumped structure for the line being dumped
+ * @param int $depth The recursive depth in the dumped structure for the line being dumped,
+ * or -1 to signal the end-of-dump to the line dumper callable
*/
protected function dumpLine($depth)
{
diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php
index 55d199ebe1ddd..acc27b96d6ef1 100644
--- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php
+++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php
@@ -132,10 +132,10 @@ protected function getDumpHeader()
function toggle(a, recursive) {
var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass;
- if ('sf-dump-compact' == oldClass) {
+ if (/\bsf-dump-compact\b/.test(oldClass)) {
arrow = '▼';
newClass = 'sf-dump-expanded';
- } else if ('sf-dump-expanded' == oldClass) {
+ } else if (/\bsf-dump-expanded\b/.test(oldClass)) {
arrow = '▶';
newClass = 'sf-dump-compact';
} else {
@@ -143,13 +143,13 @@ function toggle(a, recursive) {
}
a.lastChild.innerHTML = arrow;
- s.className = newClass;
+ s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass);
if (recursive) {
try {
a = s.querySelectorAll('.'+oldClass);
for (s = 0; s < a.length; ++s) {
- if (a[s].className !== newClass) {
+ if (-1 == a[s].className.indexOf(newClass)) {
a[s].className = newClass;
a[s].previousSibling.lastChild.innerHTML = arrow;
}
@@ -205,7 +205,7 @@ function isCtrlKey(e) {
if (f && t && f[0] !== t[0]) {
r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]);
}
- if ('sf-dump-compact' == r.className) {
+ if (/\bsf-dump-compact\b/.test(r.className)) {
toggle(s, isCtrlKey(e));
}
}
@@ -255,10 +255,10 @@ function isCtrlKey(e) {
a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children';
a.innerHTML += '▼';
a.className += ' sf-dump-toggle';
- if ('sf-dump' != elt.parentNode.className) {
+ if (!/\bsf-dump\b/.test(elt.parentNode.className)) {
toggle(a);
}
- } else if ("sf-dump-ref" == elt.className && (a = elt.getAttribute('href'))) {
+ } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) {
a = a.substr(1);
elt.className += ' '+a;