diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 776653657e..5e137e4366 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,34 @@ 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.25 (2017-03-06) + + * bug #21671 [Serializer] Xml encoder throws exception for valid data (gr1ev0us) + * bug #21805 Provide less state in getRequestFormat (dawehner) + * bug #21832 [Routing] Ignore hidden directories when loading routes from annotations (jakzal) + * bug #21769 [Form] Improve rounding precision (foaly-nr1) + * bug #21267 [Form] Fix ChoiceType to ensure submitted data is not nested unnecessarily (issei-m) + * bug #21731 Fix emacs link (rubenrua) + * bug #21800 Fix issues reported by static analyze (romainneutron) + * bug #21798 Revert "bug #21791 [SecurityBundle] only pass relevant user provider (xabbuh)" (xabbuh) + * bug #21791 [SecurityBundle] only pass relevant user provider (xabbuh) + * bug #21756 [Yaml] Stop replacing NULLs when merging (gadelat) + * bug #21722 [ExpressionLanguage] Registering functions after calling evaluate(), compile() or parse() is not supported (maidmaid) + * bug #21679 [SecurityBundle] fix priority ordering of security voters (xabbuh) + * bug #21115 [Validator] do not guess getter method names (xabbuh) + * bug #21661 Fix Composer constraints (fabpot) + * bug #21582 [HttpCache] purge both http and https from http cache (dbu) + * bug #21637 [FrameworkBundle] remove translation data collector when not usable (xabbuh) + * bug #21634 [VarDumper] Added missing persistent stream cast (lyrixx) + * bug #21436 [DependencyInjection] check for circular refs caused by method calls (xabbuh) + * bug #21400 [Serializer] fix upper camel case conversion (see #21399) (markusu49) + * bug #21599 [Console][Table] fixed render when using multiple rowspans. (aitboudad) + * bug #21613 [Process] Permit empty suffix on Windows (Bilge) + * bug #21057 [DI] Auto register extension configuration classes as a resource (ro0NL) + * bug #21592 [Validator] property constraints can be added in child classes (angelk, xabbuh) + * bug #21458 [Config] Early return for DirectoryResource (robfrawley) + * bug #21562 [DoctrineBridge] make sure that null can be the invalid value (xabbuh) + * 2.7.24 (2017-02-06) * bug #21063 [Form] Fixed DateType format option for single text widget (HeahDude) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index dd5f4d1095..73387b9f7b 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -29,34 +29,34 @@ Symfony is the result of the work of many people who made the code better - Grégoire Pineau (lyrixx) - Martin Hasoň (hason) - Jeremy Mikola (jmikola) + - Maxime Steinhausser (ogizanagi) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Maxime Steinhausser (ogizanagi) - - Eriksen Costa (eriksencosta) - Robin Chalas (chalas_r) + - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - Sarah Khalil (saro0h) - Jonathan Wage (jwage) - Diego Saint Esteben (dosten) - Alexandre Salomé (alexandresalome) - William Durand (couac) + - Guilhem Niot (energetick) - ornicar - Francis Besset (francisbesset) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - Bulat Shakirzyanov (avalanche123) - - Ener-Getick (energetick) + - Peter Rehm (rpet) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - - Miha Vrhovnik - - Diego Saint Esteben (dii3g0) - Roland Franssen (ro0) - - Konstantin Kudryashov (everzet) + - Miha Vrhovnik - Iltar van der Berg (kjarli) + - Diego Saint Esteben (dii3g0) + - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - - Peter Rehm (rpet) - Kevin Bond (kbond) - Andrej Hudec (pulzarraider) - Gábor Egyed (1ed) @@ -69,15 +69,15 @@ Symfony is the result of the work of many people who made the code better - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Douglas Greenshields (shieldo) - Titouan Galopin (tgalopin) + - Douglas Greenshields (shieldo) + - Pierre du Plessis (pierredup) - Konstantin Myakshin (koc) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) - Graham Campbell (graham) - Daniel Holmes (dholmes) - - Pierre du Plessis (pierredup) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) @@ -91,14 +91,15 @@ Symfony is the result of the work of many people who made the code better - Jérôme Tamarelle (gromnan) - Michal Piotrowski (eventhorizon) - Tim Nagel (merk) + - Maxime STEINHAUSSER + - Issei Murasawa (issei_m) - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) - marc.weistroff - - Issei Murasawa (issei_m) - lenar - Włodzimierz Gajda (gajdaw) - Baptiste Clavié (talus) - - Maxime STEINHAUSSER + - Vladimir Reznichenko (kalessil) - Alexander Schwenn (xelaris) - Florian Voutzinos (florianv) - Colin Frei @@ -106,20 +107,21 @@ Symfony is the result of the work of many people who made the code better - Adrien Brault (adrienbrault) - Joshua Thijssen - Peter Kokot (maastermedia) + - David Buchmann (dbu) - excelwebzone - Jacob Dreesen (jdreesen) - - Vladimir Reznichenko (kalessil) + - Tobias Nyholm (tobias) - Tomáš Votruba (tomas_votruba) - - David Buchmann (dbu) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - - Tobias Nyholm (tobias) - Eric GELOEN (gelo) + - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - Théo FIDRY (theofidry) - Robert Schönthal (digitalkaoz) - Florian Lonqueu-Brochard (florianlb) - Stefano Sala (stefano.sala) + - Yonel Ceruto González (yonelceruto) - Evgeniy (ewgraf) - Juti Noppornpitak (shiroyuki) - Tigran Azatyan (tigranazatyan) @@ -127,7 +129,6 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Sebastiaan Stok (sstok) - - Yonel Ceruto González (yonelceruto) - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) @@ -155,10 +156,11 @@ Symfony is the result of the work of many people who made the code better - Jonathan Ingram (jonathaningram) - Artur Kotyrba - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) + - James Halsall (jaitsu) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - - Daniel Wehner + - Grégoire Paris (greg0ire) - Possum - Dorian Villet (gnutix) - Richard Miller (mr_r_miller) @@ -171,6 +173,7 @@ Symfony is the result of the work of many people who made the code better - Lars Strojny (lstrojny) - Stepan Anchugov (kix) - bronze1man + - Daniel Espendiller - sun (sun) - Larry Garfield (crell) - Martin Schuhfuß (usefulthink) @@ -186,15 +189,14 @@ Symfony is the result of the work of many people who made the code better - Dustin Whittle (dustinwhittle) - jeff - John Kary (johnkary) - - James Halsall (jaitsu) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - Chris Wilkinson (thewilkybarkid) + - Christian Schmidt - Michele Orselli (orso) - Tom Van Looy (tvlooy) - Sven Paulus (subsven) - Rui Marinho (ruimarinho) - - Daniel Espendiller - SpacePossum - Dawid Nowak - Eugene Wissner @@ -217,8 +219,9 @@ Symfony is the result of the work of many people who made the code better - Manuel Reinhard (sprain) - Danny Berger (dpb587) - Jérôme Vasseur + - Ruben Gonzalez (rubenrua) + - Adam Prager (padam87) - Roman Marintšenko (inori) - - Christian Schmidt - Xavier Montaña Carreras (xmontana) - Mickaël Andrieu (mickaelandrieu) - Xavier Perez @@ -233,12 +236,12 @@ Symfony is the result of the work of many people who made the code better - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - Filippo Tessarotto + - Julien Falque (julienfalque) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon - Jan Sorgalla (jsor) - Ray - - Grégoire Paris (greg0ire) - Leo Feyer - Chekote - Thomas Adam @@ -255,22 +258,20 @@ Symfony is the result of the work of many people who made the code better - Beau Simensen (simensen) - Michael Hirschler (mvhirsch) - Robert Kiss (kepten) - - Ruben Gonzalez (rubenrua) + - David Maicher (dmaicher) - Roumen Damianoff (roumen) - - Adam Prager (padam87) - Antonio J. García Lagar (ajgarlag) - Kim Hemsø Rasmussen (kimhemsoe) - Wouter Van Hecke - Peter Kruithof (pkruithof) - Michael Holm (hollo) - Marc Weistroff (futurecat) + - Christian Schmidt - Hidde Wieringa (hiddewie) - Chris Smith (cs278) - Florian Klein (docteurklein) - - Julien Falque (julienfalque) - Oleg Voronkovich - Manuel Kiessling (manuelkiessling) - - Daniel Wehner - Atsuhiro KUBO (iteman) - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) @@ -310,10 +311,10 @@ 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) - - David Maicher (dmaicher) - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Tomasz Kowalczyk (thunderer) @@ -341,6 +342,7 @@ Symfony is the result of the work of many people who made the code better - Vyacheslav Salakhutdinov (megazoll) - Jerzy Zawadzki (jzawadzki) - Hassan Amouhzi + - gadelat (gadelat) - Tamas Szijarto - Pavel Volokitin (pvolok) - François Pluchino (francoispluchino) @@ -396,13 +398,13 @@ Symfony is the result of the work of many people who made the code better - Asier Illarramendi (doup) - Chris Sedlmayr (catchamonkey) - Seb Koelen + - Dany Maillard (maidmaid) - Christoph Mewes (xrstf) - Vitaliy Tverdokhlib (vitaliytv) - Ariel Ferrandini (aferrandini) - Dirk Pahl (dirkaholic) - cedric lombardot (cedriclombardot) - Jonas Flodén (flojon) - - Christian Schmidt - Amrouche Hamza - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) @@ -526,7 +528,6 @@ Symfony is the result of the work of many people who made the code better - Konstantin S. M. Möllers (ksmmoellers) - Sinan Eldem - Alexandre Dupuy (satchette) - - Rob Frawley 2nd - Andre Rømcke (andrerom) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) @@ -566,6 +567,7 @@ Symfony is the result of the work of many people who made the code better - Miquel Rodríguez Telep (mrtorrent) - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski + - Denis Brumann (dbrumann) - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - Ulumuddin Yunus (joenoez) @@ -684,6 +686,7 @@ Symfony is the result of the work of many people who made the code better - Abhoryo - Fabian Vogler (fabian) - Korvin Szanto + - Arjan Keeman - Alaattin Kahramanlar (alaattin) - Sergey Zolotov (enleur) - Maksim Kotlyar (makasim) @@ -779,6 +782,7 @@ Symfony is the result of the work of many people who made the code better - Phan Thanh Ha (haphan) - Chris Jones (leek) - Colin O'Dell (colinodell) + - Frank de Jonge (frenkynet) - xaav - Mahmoud Mostafa (mahmoud) - Alessandro Lai @@ -807,6 +811,7 @@ Symfony is the result of the work of many people who made the code better - mcfedr (mcfedr) - hamza - dantleech + - Bastien DURAND (deamon) - Xavier Leune - Tero Alén (tero) - DerManoMann @@ -832,7 +837,7 @@ Symfony is the result of the work of many people who made the code better - Nicolas Macherey - Lin Clark - Jeremy David (jeremy.david) - - Denis Brumann (dbrumann) + - Robin Lehrmann (robinlehrmann) - Troy McCabe - Ville Mattila - ilyes kooli @@ -845,6 +850,7 @@ Symfony is the result of the work of many people who made the code better - Sergey Novikov (s12v) - Marcos Quesada (marcos_quesada) - Matthew Vickery (mattvick) + - Angel Koilov (po_taka) - Dan Finnie - Ken Marfilla (marfillaster) - benatespina (benatespina) @@ -936,12 +942,14 @@ Symfony is the result of the work of many people who made the code better - Christian Sciberras - Clement Herreman (clemherreman) - Dan Ionut Dumitriu (danionut90) + - Vladislav Rastrusny (fractalizer) - Nyro (nyro) - Marco - Marc Torres - Alberto Aldegheri - heccjj - Alexandre Melard + - Jay Klehr - Sergey Yuferev - Tobias Stöckler - Mario Young @@ -999,6 +1007,7 @@ Symfony is the result of the work of many people who made the code better - Andy Raines - Anthony Ferrara - Klaas Cuvelier (kcuvelier) + - markusu49 - Steve Frécinaux - ShiraNai7 - Vašek Purchart (vasek-purchart) @@ -1024,6 +1033,7 @@ Symfony is the result of the work of many people who made the code better - Tom Corrigan (tomcorrigan) - Luis Galeas - Martin Pärtel + - George Mponos (gmponos) - Noah Heck (myesain) - Patrick Daley (padrig) - Xavier Briand (xavierbriand) @@ -1131,10 +1141,9 @@ Symfony is the result of the work of many people who made the code better - Leonid Terentyev (li0n) - ryunosuke - victoria - - Arjan Keeman - Francisco Facioni (fran6co) - Iwan van Staveren (istaveren) - - Dany Maillard (maidmaid) + - Thierry Thuon (lepiaf) - Povilas S. (povilas) - pborreli - Eric Caron @@ -1177,6 +1186,7 @@ Symfony is the result of the work of many people who made the code better - Dennis Væversted - nuncanada - flack + - izzyp - František Bereň - Christoph Nissle (derstoffel) - Ionel Scutelnicu (ionelscutelnicu) @@ -1243,6 +1253,7 @@ Symfony is the result of the work of many people who made the code better - Yannick Warnier (ywarnier) - Kevin Decherf - Jason Woods + - klemens - dened - Dmitry Korotovsky - Michael van Tricht @@ -1296,6 +1307,7 @@ Symfony is the result of the work of many people who made the code better - John Nickell (jrnickell) - Martin Mayer (martin) - Grzegorz Łukaszewicz (newicz) + - Jonny Schmid (schmidjon) - Götz Gottwald - Veres Lajos - Michael Babker @@ -1361,10 +1373,12 @@ Symfony is the result of the work of many people who made the code better - Jelle Bekker (jbekker) - Ian Jenkins (jenkoian) - Jorge Martin (jorgemartind) + - Joeri Verdeyen (jverdeyen) - Kevin Herrera (kherge) - Luis Ramón López López (lrlopez) - Muriel (metalmumu) - Michael Pohlers (mick_the_big) + - mlpo (mlpo) - Cayetano Soriano Gallego (neoshadybeat) - Ondrej Machulda (ondram) - Pablo Monterde Perez (plebs) @@ -1424,6 +1438,7 @@ Symfony is the result of the work of many people who made the code better - Christian Eikermann - Antonio Angelino - Shawn Iwinski + - Niklas Keller - Vladimir Sazhin - lol768 - jamogon @@ -1512,6 +1527,7 @@ Symfony is the result of the work of many people who made the code better - Lin Lu - arduanov - sualko + - Bilge - Nicolas Roudaire - Alfonso (afgar) - Andreas Forsblom (aforsblo) @@ -1527,6 +1543,7 @@ Symfony is the result of the work of many people who made the code better - Choong Wei Tjeng (choonge) - Kousuke Ebihara (co3k) - Loïc Vernet (coil) + - Christian Gripp (core23) - Christoph Schaefer (cvschaefer) - Damon Jones (damon__jones) - Łukasz Giza (destroyer) @@ -1582,6 +1599,7 @@ Symfony is the result of the work of many people who made the code better - Bart Ruysseveldt (ruyss) - Sascha Dens (saschadens) - scourgen hung (scourgen) + - Sébastien Alfaiate (seb33300) - Sebastian Busch (sebu) - André Filipe Gonçalves Neves (seven) - Bruno Ziegler (sfcoder) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 85d5831736..b7d3593cad 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -568,7 +568,10 @@ class Filesystem } $this->chmod($tmpFile, $mode); + } elseif (file_exists($filename)) { + @chmod($tmpFile, fileperms($filename)); } + $this->rename($tmpFile, $filename, true); } diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index b0dc47a602..1913f4fbb5 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1180,6 +1180,19 @@ class FilesystemTest extends FilesystemTestCase $this->assertSame('bar', file_get_contents($filename)); } + public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile() + { + $this->markAsSkippedIfChmodIsMissing(); + + $filename = $this->workspace.DIRECTORY_SEPARATOR.'foo.txt'; + file_put_contents($filename, 'FOO BAR'); + chmod($filename, 0745); + + $this->filesystem->dumpFile($filename, 'bar', null); + + $this->assertFilePermissions(745, $filename); + } + public function testCopyShouldKeepExecutionPermission() { $this->markAsSkippedIfChmodIsMissing(); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php index 663cdd0339..cb6000aa8f 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php @@ -23,6 +23,7 @@ abstract class TypeTestCase extends BaseTypeTestCase $this->validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $this->validator->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata)); + $this->validator->expects($this->any())->method('validate')->will($this->returnValue(array())); parent::setUp(); } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index e75eea5a81..97cc511197 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -303,6 +303,9 @@ abstract class Kernel implements KernelInterface, TerminableInterface { if (null === $this->name) { $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); + if (ctype_digit($this->name[0])) { + $this->name = '_'.$this->name; + } } return $this->name; diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/123/Kernel123.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/123/Kernel123.php new file mode 100644 index 0000000000..b6cf1cba20 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/123/Kernel123.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\_123; + +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\Config\Loader\LoaderInterface; + +class Kernel123 extends Kernel +{ + public function registerBundles() + { + return array(); + } + + public function registerContainerConfiguration(LoaderInterface $loader) + { + } + + public function getCacheDir() + { + return sys_get_temp_dir().'/'.Kernel::VERSION.'/kernel123/cache/'.$this->environment; + } + + public function getLogDir() + { + return sys_get_temp_dir().'/'.Kernel::VERSION.'/kernel123/logs'; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 8d4ebd7215..dad52401da 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -762,6 +762,14 @@ EOF; $kernel->terminate(Request::create('/'), new Response()); } + public function testKernelRootDirNameStartingWithANumber() + { + $dir = __DIR__.'/Fixtures/123'; + require_once $dir.'/Kernel123.php'; + $kernel = new \Symfony\Component\HttpKernel\Tests\Fixtures\_123\Kernel123('dev', true); + $this->assertEquals('_123', $kernel->getName()); + } + /** * Returns a mock for the BundleInterface. * diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 9ac37cdf6d..b443fa1488 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -150,6 +150,8 @@ class ContextListener implements ListenerInterface return $token; } + $userNotFoundByProvider = false; + foreach ($this->userProviders as $provider) { try { $refreshedUser = $provider->refreshUser($user); @@ -167,10 +169,14 @@ class ContextListener implements ListenerInterface $this->logger->warning('Username could not be found in the selected user provider.', array('username' => $e->getUsername(), 'provider' => get_class($provider))); } - return; + $userNotFoundByProvider = true; } } + if ($userNotFoundByProvider) { + return; + } + throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user))); } } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 15bc8bda69..ba8edc3b17 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -17,10 +17,17 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\Exception\UnsupportedUserException; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; +use Symfony\Component\Security\Core\User\User; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Http\Firewall\ContextListener; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -238,6 +245,40 @@ class ContextListenerTest extends TestCase $listener->handle($event); } + public function testTryAllUserProvidersUntilASupportingUserProviderIsFound() + { + $tokenStorage = new TokenStorage(); + $refreshedUser = new User('foobar', 'baz'); + $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser))); + + $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); + } + + public function testNextSupportingUserProviderIsTriedIfPreviousSupportingUserProviderDidNotLoadTheUser() + { + $tokenStorage = new TokenStorage(); + $refreshedUser = new User('foobar', 'baz'); + $this->handleEventWithPreviousSession($tokenStorage, array(new SupportingUserProvider(), new SupportingUserProvider($refreshedUser))); + + $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); + } + + public function testTokenIsSetToNullIfNoUserWasLoadedByTheRegisteredUserProviders() + { + $tokenStorage = new TokenStorage(); + $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider())); + + $this->assertNull($tokenStorage->getToken()); + } + + /** + * @expectedException \RuntimeException + */ + public function testRuntimeExceptionIsThrownIfNoSupportingUserProviderWasRegistered() + { + $this->handleEventWithPreviousSession(new TokenStorage(), array(new NotSupportingUserProvider(), new NotSupportingUserProvider())); + } + protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); @@ -265,4 +306,67 @@ class ContextListenerTest extends TestCase return $session; } + + private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, array $userProviders) + { + $session = new Session(new MockArraySessionStorage()); + $session->set('_security_context_key', serialize(new UsernamePasswordToken(new User('foo', 'bar'), '', 'context_key'))); + + $request = new Request(); + $request->setSession($session); + $request->cookies->set('MOCKSESSID', true); + + $listener = new ContextListener($tokenStorage, $userProviders, 'context_key'); + $listener->handle(new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST)); + } +} + +class NotSupportingUserProvider implements UserProviderInterface +{ + public function loadUserByUsername($username) + { + throw new UsernameNotFoundException(); + } + + public function refreshUser(UserInterface $user) + { + throw new UnsupportedUserException(); + } + + public function supportsClass($class) + { + return false; + } +} + +class SupportingUserProvider implements UserProviderInterface +{ + private $refreshedUser; + + public function __construct(User $refreshedUser = null) + { + $this->refreshedUser = $refreshedUser; + } + + public function loadUserByUsername($username) + { + } + + public function refreshUser(UserInterface $user) + { + if (!$user instanceof User) { + throw new UnsupportedUserException(); + } + + if (null === $this->refreshedUser) { + throw new UsernameNotFoundException(); + } + + return $this->refreshedUser; + } + + public function supportsClass($class) + { + return 'Symfony\Component\Security\Core\User\User' === $class; + } }