Merge branch '4.4' into 5.0

* 4.4:
  Fix versions
  [Security/Http] Allow setting cookie security settings for delete_cookies
  [DI] fix generating TypedReference from PriorityTaggedServiceTrait
  [FrameworkBundle] revert to legacy wiring of the session when circular refs are detected
  bumped Symfony version to 3.4.40
  updated VERSION for 3.4.39
  update CONTRIBUTORS for 3.4.39
  updated CHANGELOG for 3.4.39
  [DomCrawler] Fix BC break in assertions breaking Panther
  [BrowserKit] fixed missing post request parameters in file uploads
  update Italian translation
  [Validator] Add missing Hungarian translations
  [Validator] Add the missing translations for the Arabic (ar) locale
  [Validator] Add missing vietnamese translations
  [Console] Fix OutputStream for PHP 7.4
  add German translations
  bug #36157 [Validator] Assert Valid with many groups
  [Validator] Add missing Lithuanian translations
  Fixed some typos
  Add french "at least" constraint translations
This commit is contained in:
Nicolas Grekas 2020-03-30 13:42:42 +02:00
commit 6b0ad43856
31 changed files with 334 additions and 63 deletions

View File

@ -16,27 +16,27 @@ Symfony is the result of the work of many people who made the code better
- Victor Berchet (victor)
- Maxime Steinhausser (ogizanagi)
- Ryan Weaver (weaverryan)
- Javier Eguiluz (javier.eguiluz)
- Grégoire Pineau (lyrixx)
- Jakub Zalas (jakubzalas)
- Javier Eguiluz (javier.eguiluz)
- Roland Franssen (ro0)
- Jakub Zalas (jakubzalas)
- Johannes S (johannes)
- Kris Wallsmith (kriswallsmith)
- Yonel Ceruto (yonelceruto)
- Hugo Hamon (hhamon)
- Abdellatif Ait boudad (aitboudad)
- Samuel ROZE (sroze)
- Romain Neutron (romain)
- Wouter de Jong (wouterj)
- Pascal Borreli (pborreli)
- Thomas Calvet (fancyweb)
- Wouter de Jong (wouterj)
- Romain Neutron (romain)
- Pascal Borreli (pborreli)
- Joseph Bielawski (stloyd)
- Alexander M. Turek (derrabus)
- Karma Dordrak (drak)
- Lukas Kahwe Smith (lsmith)
- Martin Hasoň (hason)
- Hamza Amrouche (simperfit)
- Jules Pietri (heah)
- Hamza Amrouche (simperfit)
- Martin Hasoň (hason)
- Jeremy Mikola (jmikola)
- Jérémy DERUSSÉ (jderusse)
- Jean-François Simon (jfsimon)
@ -66,17 +66,17 @@ Symfony is the result of the work of many people who made the code better
- Saša Stamenković (umpirsky)
- Peter Rehm (rpet)
- Henrik Bjørnskov (henrikbjorn)
- Miha Vrhovnik
- Gabriel Ostrolucký (gadelat)
- Miha Vrhovnik
- David Maicher (dmaicher)
- Diego Saint Esteben (dii3g0)
- Gábor Egyed (1ed)
- Titouan Galopin (tgalopin)
- David Maicher (dmaicher)
- Jan Schädlich (jschaedl)
- Konstantin Kudryashov (everzet)
- Bilal Amarni (bamarni)
- Mathieu Piot (mpiot)
- Vladimir Reznichenko (kalessil)
- Jan Schädlich (jschaedl)
- Florin Patan (florinpatan)
- Jáchym Toušek (enumag)
- Andrej Hudec (pulzarraider)
@ -136,6 +136,7 @@ Symfony is the result of the work of many people who made the code better
- Joel Wurtz (brouznouf)
- Fabien Pennequin (fabienpennequin)
- Théo FIDRY (theofidry)
- Przemysław Bogusz (przemyslaw-bogusz)
- Eric GELOEN (gelo)
- Lars Strojny (lstrojny)
- Jannik Zschiesche (apfelbox)
@ -155,6 +156,7 @@ Symfony is the result of the work of many people who made the code better
- Sebastian Hörl (blogsh)
- Daniel Gomes (danielcsgomes)
- Hidenori Goto (hidenorigoto)
- Alessandro Chitolina (alekitto)
- Andréia Bohner (andreia)
- Yanick Witschi (toflar)
- Arnaud Kleinpeter (nanocom)
@ -164,7 +166,6 @@ Symfony is the result of the work of many people who made the code better
- Jérémie Augustin (jaugustin)
- François-Xavier de Guillebon (de-gui_f)
- Oleg Voronkovich
- Alessandro Chitolina (alekitto)
- Philipp Wahala (hifi)
- Rafael Dohms (rdohms)
- jwdeitch
@ -239,8 +240,10 @@ Symfony is the result of the work of many people who made the code better
- fivestar
- Dominique Bongiraud
- Jeremy Livingston (jeremylivingston)
- Laurent VOULLEMIER (lvo)
- Michael Lee (zerustech)
- Matthieu Auger (matthieuauger)
- Ahmed TAILOULOUTE (ahmedtai)
- Leszek Prabucki (l3l0)
- Fabien Bourigault (fbourigault)
- François Zaninotto (fzaninotto)
@ -248,7 +251,6 @@ Symfony is the result of the work of many people who made the code better
- jeff
- John Kary (johnkary)
- Jan Rosier (rosier)
- Przemysław Bogusz (przemyslaw-bogusz)
- Justin Hileman (bobthecow)
- Blanchon Vincent (blanchonvincent)
- Michele Orselli (orso)
@ -280,7 +282,6 @@ Symfony is the result of the work of many people who made the code better
- julien pauli (jpauli)
- Lorenz Schori
- Sébastien Lavoie (lavoiesl)
- Ahmed TAILOULOUTE (ahmedtai)
- Dariusz
- Saif (╯°□°)╯ (azjezz)
- Dmitrii Poddubnyi (karser)
@ -306,6 +307,7 @@ Symfony is the result of the work of many people who made the code better
- Arjen Brouwer (arjenjb)
- Katsuhiro OGAWA
- Patrick McDougle (patrick-mcdougle)
- Guillaume Pédelagrabe
- Alif Rachmawadi
- Anton Chernikov (anton_ch1989)
- Kristen Gilden (kgilden)
@ -336,6 +338,7 @@ Symfony is the result of the work of many people who made the code better
- Wodor Wodorski
- Thomas Lallement (raziel057)
- Colin O'Dell (colinodell)
- Mathias Arlaud (mtarld)
- Giorgio Premi
- renanbr
- Alex Rock (pierstoval)
@ -398,13 +401,11 @@ Symfony is the result of the work of many people who made the code better
- Emanuele Gaspari (inmarelibero)
- Dariusz Rumiński
- Berny Cantos (xphere81)
- Laurent VOULLEMIER (lvo)
- Thierry Thuon (lepiaf)
- Ricard Clau (ricardclau)
- Mark Challoner (markchalloner)
- Philippe Segatori
- Gennady Telegin (gtelegin)
- Mathias Arlaud (mtarld)
- Erin Millard
- Artur Melo (restless)
- Matthew Lewinski (lewinski)
@ -433,6 +434,7 @@ Symfony is the result of the work of many people who made the code better
- Eric Masoero (eric-masoero)
- Denis Brumann (dbrumann)
- JhonnyL
- Haralan Dobrev (hkdobrev)
- hossein zolfi (ocean)
- Clément Gautier (clementgautier)
- Bastien Jaillot (bastnic)
@ -486,6 +488,7 @@ Symfony is the result of the work of many people who made the code better
- Xavier HAUSHERR
- Albert Jessurum (ajessu)
- Laszlo Korte
- Jesse Rushlow (geeshoe)
- Miha Vrhovnik
- Alessandro Desantis
- hubert lecorche (hlecorche)
@ -561,6 +564,7 @@ Symfony is the result of the work of many people who made the code better
- Gintautas Miselis
- Rob Bast
- Roberto Espinoza (respinoza)
- HypeMC
- Soufian EZ-ZANTAR (soezz)
- Zander Baldwin
- Gocha Ossinkine (ossinkine)
@ -586,7 +590,6 @@ Symfony is the result of the work of many people who made the code better
- Yoshio HANAWA
- Jan van Thoor (janvt)
- Gladhon
- Haralan Dobrev (hkdobrev)
- Sebastian Bergmann
- Miroslav Sustek
- Pablo Díez (pablodip)
@ -716,6 +719,7 @@ Symfony is the result of the work of many people who made the code better
- Stéphane Escandell (sescandell)
- Konstantin S. M. Möllers (ksmmoellers)
- James Johnston
- Noémi Salaün (noemi-salaun)
- Sinan Eldem
- BoShurik
- Alexandre Dupuy (satchette)
@ -732,6 +736,7 @@ Symfony is the result of the work of many people who made the code better
- Stefan Gehrig (sgehrig)
- Hany el-Kerdany
- Wang Jingyu
- Langlet Vincent (deviling)
- Åsmund Garfors
- Gunnstein Lye (glye)
- Maxime Douailin
@ -802,7 +807,6 @@ Symfony is the result of the work of many people who made the code better
- Simon Schick (simonsimcity)
- redstar504
- Tristan Roussel
- HypeMC
- Cameron Porter
- Hossein Bukhamsin
- Oliver Hoff
@ -835,6 +839,7 @@ Symfony is the result of the work of many people who made the code better
- Richard Quadling
- Raphaëll Roussel
- Michael Lutz
- Koen Reiniers (koenre)
- jochenvdv
- Reedy
- Arturas Smorgun (asarturas)
@ -883,6 +888,7 @@ Symfony is the result of the work of many people who made the code better
- Dennis Hotson
- Andrew Tchircoff (andrewtch)
- michaelwilliams
- Martin Kirilov
- 1emming
- Nykopol (nykopol)
- Tri Pham (phamuyentri)
@ -951,9 +957,11 @@ Symfony is the result of the work of many people who made the code better
- Roy Klutman (royklutman)
- Sofiane HADDAG (sofhad)
- frost-nzcr4
- arai
- Laurent Bassin (lbassin)
- andrey1s
- Abhoryo
- Daniel STANCU
- Fabian Vogler (fabian)
- Korvin Szanto
- soyuka
@ -1003,13 +1011,13 @@ Symfony is the result of the work of many people who made the code better
- Shin Ohno (ganchiku)
- Geert De Deckere (geertdd)
- Jan Kramer (jankramer)
- Matthieu Mota (matthieumota)
- abdul malik ikhsan (samsonasik)
- Henry Snoek (snoek09)
- Jérémy M (th3mouk)
- Simone Di Maulo (toretto460)
- Christian Morgan
- Alexander Miehe (engerim)
- Jesse Rushlow (geeshoe)
- Morgan Auchede (mauchede)
- Sascha Dens (saschadens)
- Don Pinkster
@ -1037,6 +1045,7 @@ Symfony is the result of the work of many people who made the code better
- Marcos Gómez Vilches (markitosgv)
- Matthew Davis (mdavis1982)
- Markus S. (staabm)
- Benjamin Morel
- Maks
- Antoine LA
- den
@ -1228,6 +1237,7 @@ Symfony is the result of the work of many people who made the code better
- Benjamin Paap (benjaminpaap)
- Claus Due (namelesscoder)
- Christian
- William Arslett
- Denis Golubovskiy (bukashk0zzz)
- Sergii Smertin (nfx)
- Mikkel Paulson
@ -1309,6 +1319,7 @@ Symfony is the result of the work of many people who made the code better
- BRAMILLE Sébastien (oktapodia)
- Artem Kolesnikov (tyomo4ka)
- Gustavo Adrian
- Jorrit Schippers (jorrit)
- Yannick
- Vladimir Luchaninov (luchaninov)
- spdionis
@ -1346,7 +1357,6 @@ Symfony is the result of the work of many people who made the code better
- Oxan van Leeuwen
- pkowalczyk
- Soner Sayakci
- Koen Reiniers (koenre)
- Max Voloshin (maxvoloshin)
- Nicolas Fabre (nfabre)
- Raul Rodriguez (raul782)
@ -1593,6 +1603,7 @@ Symfony is the result of the work of many people who made the code better
- Felipy Tavares Amorim (felipyamorim)
- Guillaume Loulier (guikingone)
- Klaus Silveira (klaussilveira)
- Pierre Grimaud (pgrimaud)
- Thomas Chmielowiec (chmielot)
- Jānis Lukss
- rkerner
@ -1645,7 +1656,9 @@ Symfony is the result of the work of many people who made the code better
- Mephistofeles
- Hoffmann András
- LubenZA
- Victor Garcia
- Olivier
- Denis Yuzhanin
- knezmilos13
- Cyril PASCAL
- Michael Bessolov
@ -1732,6 +1745,7 @@ Symfony is the result of the work of many people who made the code better
- Stefan Hüsges (tronsha)
- Jake Bishop (yakobeyak)
- Dan Blows
- popnikos
- Matt Wells
- Sander van der Vlugt
- Nicolas Appriou
@ -1828,6 +1842,7 @@ Symfony is the result of the work of many people who made the code better
- Aarón Nieves Fernández
- Mike Meier
- Kirill Saksin
- Reda DAOUDI
- Koalabaerchen
- michalmarcinkowski
- Warwick
@ -1873,7 +1888,6 @@ Symfony is the result of the work of many people who made the code better
- ged15
- Daan van Renterghem
- Nicole Cordes
- Martin Kirilov
- Bálint Szekeres
- amcastror
- Alexander Li (aweelex)
@ -2174,7 +2188,6 @@ Symfony is the result of the work of many people who made the code better
- Karolis
- Myke79
- Brian Debuire
- Benjamin Morel
- Eric Grimois
- Piers Warmers
- Sylvain Lorinet
@ -2240,7 +2253,6 @@ Symfony is the result of the work of many people who made the code better
- James Michael DuPont
- Kasperki
- Tammy D
- Daniel STANCU
- Ryan Rud
- Ondrej Slinták
- vlechemin
@ -2267,6 +2279,7 @@ Symfony is the result of the work of many people who made the code better
- Abdulkadir N. A.
- Adam Klvač
- Bruno Nogueira Nascimento Wowk
- jonmldr
- Yevgen Kovalienia
- Lebnik
- nsbx
@ -2385,6 +2398,7 @@ Symfony is the result of the work of many people who made the code better
- Jose Manuel Gonzalez (jgonzalez)
- Joachim Krempel (jkrempel)
- Jorge Maiden (jorgemaiden)
- Joao Paulo V Martins (jpjoao)
- Justin Rainbow (jrainbow)
- Juan Luis (juanlugb)
- JuntaTom (juntatom)
@ -2398,7 +2412,6 @@ Symfony is the result of the work of many people who made the code better
- Luís Cobucci (lcobucci)
- Jérémy (libertjeremy)
- Mehdi Achour (machour)
- Matthieu Mota (matthieumota)
- Matthieu Moquet (mattketmo)
- Moritz Borgmann (mborgmann)
- Michal Čihař (mcihar)
@ -2442,6 +2455,7 @@ Symfony is the result of the work of many people who made the code better
- Markus Tacker (tacker)
- Tom Newby (tomnewbyau)
- Andrew Clark (tqt_andrew_clark)
- Aaron Piotrowski (trowski)
- David Lumaye (tux1124)
- Roman Tymoshyk (tymoshyk)
- Tyler Stroud (tystr)

View File

@ -383,8 +383,8 @@ class XmlDescriptor extends Descriptor
} elseif (\is_array($argument)) {
$argumentXML->setAttribute('type', 'collection');
foreach ($this->getArgumentNodes($argument, $dom) as $childArgumenXML) {
$argumentXML->appendChild($childArgumenXML);
foreach ($this->getArgumentNodes($argument, $dom) as $childArgumentXML) {
$argumentXML->appendChild($childArgumentXML);
}
} else {
$argumentXML->appendChild(new \DOMText($argument));

View File

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* @internal to be removed in 6.0
*/
class SessionPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition('session')) {
return;
}
$bags = [
'session.flash_bag' => $container->hasDefinition('session.flash_bag') ? $container->getDefinition('session.flash_bag') : null,
'session.attribute_bag' => $container->hasDefinition('session.attribute_bag') ? $container->getDefinition('session.attribute_bag') : null,
];
foreach ($container->getDefinition('session')->getArguments() as $v) {
if (!$v instanceof Reference || !isset($bags[$bag = (string) $v]) || !\is_array($factory = $bags[$bag]->getFactory())) {
continue;
}
if ([0, 1] !== array_keys($factory) || !$factory[0] instanceof Reference || 'session' !== (string) $factory[0]) {
continue;
}
if ('get'.ucfirst(substr($bag, 8, -4)).'Bag' !== $factory[1]) {
continue;
}
$bags[$bag]->setFactory(null);
}
}
}

View File

@ -18,6 +18,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilder
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SessionPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
@ -149,6 +150,7 @@ class FrameworkBundle extends Bundle
$this->addCompilerPassIfExists($container, AddAutoMappingConfigurationPass::class);
$container->addCompilerPass(new RegisterReverseContainerPass(true));
$container->addCompilerPass(new RegisterReverseContainerPass(false), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new SessionPass());
if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2);

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SessionPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
class SessionPassTest extends TestCase
{
public function testProcess()
{
$arguments = [
new Reference('session.flash_bag'),
new Reference('session.attribute_bag'),
];
$container = new ContainerBuilder();
$container
->register('session')
->setArguments($arguments);
$container
->register('session.flash_bag')
->setFactory([new Reference('session'), 'getFlashBag']);
$container
->register('session.attribute_bag')
->setFactory([new Reference('session'), 'getAttributeBag']);
(new SessionPass())->process($container);
$this->assertSame($arguments, $container->getDefinition('session')->getArguments());
$this->assertNull($container->getDefinition('session.flash_bag')->getFactory());
$this->assertNull($container->getDefinition('session.attribute_bag')->getFactory());
}
}

View File

@ -221,6 +221,8 @@ class MainConfiguration implements ConfigurationInterface
->children()
->scalarNode('path')->defaultNull()->end()
->scalarNode('domain')->defaultNull()->end()
->scalarNode('secure')->defaultFalse()->end()
->scalarNode('samesite')->defaultNull()->end()
->end()
->end()
->end()

View File

@ -75,7 +75,7 @@ class HttpBrowser extends AbstractBrowser
$fields = $request->getParameters();
if ($uploadedFiles = $this->getUploadedFiles($request->getFiles())) {
$part = new FormDataPart($uploadedFiles);
$part = new FormDataPart(array_merge($fields, $uploadedFiles));
return [$part->bodyToIterable(), $part->getPreparedHeaders()->toArray()];
}

View File

@ -134,6 +134,28 @@ class HttpBrowserTest extends AbstractBrowserTest
]);
}
public function testMultiPartRequestWithAdditionalParameters()
{
$client = $this->createMock(HttpClientInterface::class);
$this->expectClientToSendRequestWithFiles($client, ['file1_content', 'baz']);
$browser = new HttpBrowser($client);
$browser->request('POST', 'http://example.com/', ['bar' => 'baz'], [
'file1' => $this->getUploadedFile('file1'),
]);
}
public function testMultiPartRequestWithAdditionalParametersOfTheSameName()
{
$client = $this->createMock(HttpClientInterface::class);
$this->expectClientToNotSendRequestWithFiles($client, ['baz']);
$browser = new HttpBrowser($client);
$browser->request('POST', 'http://example.com/', ['file1' => 'baz'], [
'file1' => $this->getUploadedFile('file1'),
]);
}
private function uploadFile(string $data): string
{
$path = tempnam(sys_get_temp_dir(), 'http');
@ -167,4 +189,22 @@ class HttpBrowserTest extends AbstractBrowserTest
}))
->willReturn($this->createMock(ResponseInterface::class));
}
protected function expectClientToNotSendRequestWithFiles(HttpClientInterface $client, $fileContents)
{
$client
->expects($this->once())
->method('request')
->with('POST', 'http://example.com/', $this->callback(function ($options) use ($fileContents) {
$this->assertStringContainsString('Content-Type: multipart/form-data', implode('', $options['headers']));
$this->assertInstanceOf('\Generator', $options['body']);
$body = implode('', iterator_to_array($options['body'], false));
foreach ($fileContents as $content) {
$this->assertStringNotContainsString($content, $body);
}
return true;
}))
->willReturn($this->createMock(ResponseInterface::class));
}
}

View File

@ -12,7 +12,6 @@
namespace Symfony\Component\Console\Output;
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
@ -74,10 +73,7 @@ class StreamOutput extends Output
$message .= PHP_EOL;
}
if (false === @fwrite($this->stream, $message)) {
// should never happen
throw new RuntimeException('Unable to write output.');
}
@fwrite($this->stream, $message);
fflush($this->stream);
}

View File

@ -56,4 +56,12 @@ class StreamOutputTest extends TestCase
rewind($output->getStream());
$this->assertEquals('foo'.PHP_EOL, stream_get_contents($output->getStream()), '->doWrite() writes to the stream');
}
public function testDoWriteOnFailure()
{
$resource = fopen(__DIR__.'/../Fixtures/stream_output_file.txt', 'r', false);
$output = new StreamOutput($resource);
rewind($output->getStream());
$this->assertEquals('', stream_get_contents($output->getStream()));
}
}

View File

@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;
/**
* Trait that allows a generic method to find and sort service by priority option in the tag.
@ -55,41 +56,51 @@ trait PriorityTaggedServiceTrait
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
$defaultPriority = null;
$defaultIndex = null;
$class = $container->getDefinition($serviceId)->getClass();
$class = $container->getParameterBag()->resolveValue($class) ?: null;
foreach ($attributes as $attribute) {
$index = $priority = null;
if (isset($attribute['priority'])) {
$priority = $attribute['priority'];
} elseif (null === $defaultPriority && $defaultPriorityMethod) {
$defaultPriority = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $defaultPriorityMethod, $tagName);
} elseif (null === $defaultPriority && $defaultPriorityMethod && $class) {
$defaultPriority = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $class, $defaultPriorityMethod, $tagName);
}
$priority = $priority ?? $defaultPriority ?? $defaultPriority = 0;
if (null === $indexAttribute && !$needsIndexes) {
$services[] = [$priority, ++$i, null, $serviceId];
$services[] = [$priority, ++$i, null, $serviceId, null];
continue 2;
}
if (null !== $indexAttribute && isset($attribute[$indexAttribute])) {
$index = $attribute[$indexAttribute];
} elseif (null === $defaultIndex && $defaultIndexMethod) {
$defaultIndex = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $defaultIndexMethod, $tagName, $indexAttribute);
} elseif (null === $defaultIndex && $defaultIndexMethod && $class) {
$defaultIndex = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $class, $defaultIndexMethod, $tagName, $indexAttribute);
}
$index = $index ?? $defaultIndex ?? $defaultIndex = $serviceId;
$services[] = [$priority, ++$i, $index, $serviceId];
$services[] = [$priority, ++$i, $index, $serviceId, $class];
}
}
uasort($services, static function ($a, $b) { return $b[0] <=> $a[0] ?: $a[1] <=> $b[1]; });
$refs = [];
foreach ($services as [, , $index, $serviceId]) {
if (null === $index) {
$refs[] = new Reference($serviceId);
foreach ($services as [, , $index, $serviceId, $class]) {
if (!$class) {
$reference = new Reference($serviceId);
} elseif ($index === $serviceId) {
$reference = new TypedReference($serviceId, $class);
} else {
$refs[$index] = new Reference($serviceId);
$reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $index);
}
if (null === $index) {
$refs[] = $reference;
} else {
$refs[$index] = $reference;
}
}
@ -105,11 +116,8 @@ class PriorityTaggedServiceUtil
/**
* Gets the index defined by the default index method.
*/
public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $defaultIndexMethod, string $tagName, string $indexAttribute): ?string
public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $class, string $defaultIndexMethod, string $tagName, string $indexAttribute): ?string
{
$class = $container->getDefinition($serviceId)->getClass();
$class = $container->getParameterBag()->resolveValue($class) ?: null;
if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultIndexMethod)) {
return null;
}
@ -134,11 +142,8 @@ class PriorityTaggedServiceUtil
/**
* Gets the priority defined by the default priority method.
*/
public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $defaultPriorityMethod, string $tagName): ?int
public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $class, string $defaultPriorityMethod, string $tagName): ?int
{
$class = $container->getDefinition($serviceId)->getClass();
$class = $container->getParameterBag()->resolveValue($class) ?: null;
if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultPriorityMethod)) {
return null;
}

View File

@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\BarTagClass;
use Symfony\Component\DependencyInjection\TypedReference;
class PriorityTaggedServiceTraitTest extends TestCase
{
@ -122,10 +123,10 @@ class PriorityTaggedServiceTraitTest extends TestCase
$tag = new TaggedIteratorArgument('my_custom_tag', 'foo');
$expected = [
'bar_tag_class' => new Reference('service2'),
'b' => new Reference('service2'),
'bar_tag_class' => new TypedReference('service2', BarTagClass::class),
'b' => new TypedReference('service2', BarTagClass::class),
'bar' => new Reference('service1'),
'a' => new Reference('service2'),
'a' => new TypedReference('service2', BarTagClass::class),
];
$services = $priorityTaggedServiceTraitImplementation->test($tag, $container);
$this->assertSame(array_keys($expected), array_keys($services));

View File

@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\TypedReference;
/**
* @author Roland Franssen <franssen.roland@gmail.com>
@ -50,7 +51,7 @@ class ResolveTaggedIteratorArgumentPassTest extends TestCase
$properties = $container->getDefinition('service_c')->getProperties();
$expected = new TaggedIteratorArgument('foo', 'key');
$expected->setValues(['1' => new Reference('service_a'), '2' => new Reference('service_b')]);
$expected->setValues(['1' => new TypedReference('service_a', 'stdClass'), '2' => new TypedReference('service_b', 'stdClass')]);
$this->assertEquals($expected, $properties['foos']);
}
}

View File

@ -45,7 +45,7 @@ final class CrawlerSelectorTextContains extends Constraint
return false;
}
return false !== mb_strpos($crawler->text(null, false), $this->expectedText);
return false !== mb_strpos($crawler->text(null, true), $this->expectedText);
}
/**

View File

@ -45,7 +45,7 @@ final class CrawlerSelectorTextSame extends Constraint
return false;
}
return $this->expectedText === trim($crawler->text(null, false));
return $this->expectedText === trim($crawler->text(null, true));
}
/**

View File

@ -256,7 +256,7 @@ class RouteCollectionBuilderTest extends TestCase
// shows that a prefix will always be given the starting slash
$tests[] = ['0', '/foo', '/0/foo'];
// spaces are ok, and double slahses at the end are cleaned
// spaces are ok, and double slashes at the end are cleaned
$tests[] = ['/ /', '/foo', '/ /foo'];
return $tests;

View File

@ -38,7 +38,7 @@ class CookieClearingLogoutHandler implements LogoutHandlerInterface
public function logout(Request $request, Response $response, TokenInterface $token)
{
foreach ($this->cookies as $cookieName => $cookieData) {
$response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain']);
$response->headers->clearCookie($cookieName, $cookieData['path'], $cookieData['domain'], isset($cookieData['secure']) ? $cookieData['secure'] : false, true, isset($cookieData['samesite']) ? $cookieData['samesite'] : null);
}
}
}

View File

@ -355,7 +355,7 @@ class SwitchUserListenerTest extends TestCase
$this->assertSame($replacedToken, $this->tokenStorage->getToken());
}
public function testSwitchtUserThrowsAuthenticationExceptionIfNoCurrentToken()
public function testSwitchUserThrowsAuthenticationExceptionIfNoCurrentToken()
{
$this->expectException('Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException');
$this->tokenStorage->setToken(null);

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Http\Tests\Logout;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
@ -25,7 +26,7 @@ class CookieClearingLogoutHandlerTest extends TestCase
$response = new Response();
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$handler = new CookieClearingLogoutHandler(['foo' => ['path' => '/foo', 'domain' => 'foo.foo'], 'foo2' => ['path' => null, 'domain' => null]]);
$handler = new CookieClearingLogoutHandler(['foo' => ['path' => '/foo', 'domain' => 'foo.foo', 'secure' => true, 'samesite' => Cookie::SAMESITE_STRICT], 'foo2' => ['path' => null, 'domain' => null]]);
$cookies = $response->headers->getCookies();
$this->assertCount(0, $cookies);
@ -39,12 +40,16 @@ class CookieClearingLogoutHandlerTest extends TestCase
$this->assertEquals('foo', $cookie->getName());
$this->assertEquals('/foo', $cookie->getPath());
$this->assertEquals('foo.foo', $cookie->getDomain());
$this->assertEquals(Cookie::SAMESITE_STRICT, $cookie->getSameSite());
$this->assertTrue($cookie->isSecure());
$this->assertTrue($cookie->isCleared());
$cookie = $cookies['']['/']['foo2'];
$this->assertStringStartsWith('foo2', $cookie->getName());
$this->assertEquals('/', $cookie->getPath());
$this->assertNull($cookie->getDomain());
$this->assertNull($cookie->getSameSite());
$this->assertFalse($cookie->isSecure());
$this->assertTrue($cookie->isCleared());
}
}

View File

@ -18,7 +18,7 @@
"require": {
"php": "^7.2.5",
"symfony/security-core": "^4.4|^5.0",
"symfony/http-foundation": "^4.4|^5.0",
"symfony/http-foundation": "^4.4.7|^5.0.7",
"symfony/http-kernel": "^4.4|^5.0",
"symfony/property-access": "^4.4|^5.0"
},

View File

@ -374,6 +374,14 @@
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>يجب أن يكون عدد العناصر في هذه المجموعة مضاعف {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="97">
<source>This value should satisfy at least one of the following constraints:</source>
<target>يجب أن تستوفي هذه القيمة واحدة من القيود التالية:</target>
</trans-unit>
<trans-unit id="98">
<source>Each element of this collection should satisfy its own set of constraints.</source>
<target>يجب أن يفي كل عنصر من عناصر هذه المجموعة بمجموعة القيود الخاصة به.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -374,6 +374,14 @@
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>Die Anzahl an Elementen in dieser Sammlung sollte ein Vielfaches von {{ compared_value }} sein.</target>
</trans-unit>
<trans-unit id="97">
<source>This value should satisfy at least one of the following constraints:</source>
<target>Dieser Wert sollte eine der folgenden Bedingungen erfüllen:</target>
</trans-unit>
<trans-unit id="98">
<source>Each element of this collection should satisfy its own set of constraints.</source>
<target>Jedes Element dieser Sammlung sollte seine eigene Menge an Bedingungen erfüllen.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -374,6 +374,14 @@
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>Le nombre d'éléments de cette collection doit être un multiple de {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="97">
<source>This value should satisfy at least one of the following constraints:</source>
<target>Cette valeur doit satisfaire à au moins une des contraintes suivantes :</target>
</trans-unit>
<trans-unit id="98">
<source>Each element of this collection should satisfy its own set of constraints.</source>
<target>Chaque élément de cette collection doit satisfaire à son propre jeu de contraintes.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -366,6 +366,22 @@
<source>This value should be between {{ min }} and {{ max }}.</source>
<target>Ennek az értéknek {{ min }} és {{ max }} között kell lennie.</target>
</trans-unit>
<trans-unit id="95">
<source>This value is not a valid hostname.</source>
<target>Ez az érték nem egy érvényes állomásnév (hosztnév).</target>
</trans-unit>
<trans-unit id="96">
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>A gyűjteményben lévő elemek számának oszthatónak kell lennie a következővel: {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="97">
<source>This value should satisfy at least one of the following constraints:</source>
<target>Ennek az értéknek meg kell felelni legalább egynek a következő feltételek közül:</target>
</trans-unit>
<trans-unit id="98">
<source>Each element of this collection should satisfy its own set of constraints.</source>
<target>A gyűjtemény minden elemének meg kell felelni a saját feltételeinek.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -366,6 +366,22 @@
<source>This value should be between {{ min }} and {{ max }}.</source>
<target>Questo valore dovrebbe essere compreso tra {{ min }} e {{ max }}.</target>
</trans-unit>
<trans-unit id="95">
<source>This value is not a valid hostname.</source>
<target>Questo valore non è un nome di host valido.</target>
</trans-unit>
<trans-unit id="96">
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>Il numero di elementi in questa collezione dovrebbe essere un multiplo di {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="97">
<source>This value should satisfy at least one of the following constraints:</source>
<target>Questo valore dovrebbe soddisfare almeno uno dei vincoli seguenti:</target>
</trans-unit>
<trans-unit id="98">
<source>Each element of this collection should satisfy its own set of constraints.</source>
<target>Ciascun elemento di questa collezione dovrebbe soddisfare il suo insieme di vincoli.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -366,6 +366,22 @@
<source>This value should be between {{ min }} and {{ max }}.</source>
<target>Ši reikšmė turi būti tarp {{ min }} ir {{ max }}.</target>
</trans-unit>
<trans-unit id="95">
<source>This value is not a valid hostname.</source>
<target>Ši reikšmė nėra tinkamas svetainės adresas.</target>
</trans-unit>
<trans-unit id="96">
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>Šio sąrašo elementų skaičius turėtų būti skaičiaus {{ compared_value }} kartotinis.</target>
</trans-unit>
<trans-unit id="97">
<source>This value should satisfy at least one of the following constraints:</source>
<target>Ši reikšmė turėtų atitikti bent vieną iš šių nurodymų:</target>
</trans-unit>
<trans-unit id="98">
<source>Each element of this collection should satisfy its own set of constraints.</source>
<target>Kiekvienas šio sąrašo elementas turi atitikti savo nurodymų rinkinį.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -374,6 +374,14 @@
<source>The number of elements in this collection should be a multiple of {{ compared_value }}.</source>
<target>Số lượng các phần tử trong bộ sưu tập này nên là bội số của {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="97">
<source>This value should satisfy at least one of the following constraints:</source>
<target>Giá trị này nên thỏa mãn ít nhất một trong những ràng buộc sau:</target>
</trans-unit>
<trans-unit id="98">
<source>Each element of this collection should satisfy its own set of constraints.</source>
<target>Mỗi phần tử trong bộ sưu tập này nên thỏa mãn những ràng buộc của nó.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -698,4 +698,25 @@ abstract class AbstractTest extends AbstractValidatorTest
$this->assertCount(2, $violations);
}
public function testNestedObjectIsValidatedInMultipleGroupsIfGroupInValidConstraintIsValidated()
{
$entity = new Entity();
$entity->firstName = null;
$reference = new Reference();
$reference->value = null;
$entity->childA = $reference;
$this->metadata->addPropertyConstraint('firstName', new NotBlank());
$this->metadata->addPropertyConstraint('childA', new Valid(['groups' => ['group1', 'group2']]));
$this->referenceMetadata->addPropertyConstraint('value', new NotBlank(['groups' => 'group1']));
$this->referenceMetadata->addPropertyConstraint('value', new NotNull(['groups' => 'group2']));
$violations = $this->validator->validate($entity, null, ['Default', 'group1', 'group2']);
$this->assertCount(3, $violations);
}
}

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Validator\Validator;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Composite;
use Symfony\Component\Validator\Constraints\GroupSequence;
use Symfony\Component\Validator\Constraints\Valid;
use Symfony\Component\Validator\ConstraintValidatorFactoryInterface;
use Symfony\Component\Validator\Context\ExecutionContext;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
@ -710,8 +711,9 @@ class RecursiveContextualValidator implements ContextualValidatorInterface
// that constraints belong to multiple validated groups
if (null !== $cacheKey) {
$constraintHash = spl_object_hash($constraint);
if ($constraint instanceof Composite) {
// instanceof Valid: In case of using a Valid constraint with many groups
// it makes a reference object get validated by each group
if ($constraint instanceof Composite || $constraint instanceof Valid) {
$constraintHash .= $group;
}

View File

@ -1899,7 +1899,7 @@ YAML
$this->parser->parse('!!iterator foo');
}
public function testExceptionWhenUsingUnsuportedBuiltInTags()
public function testExceptionWhenUsingUnsupportedBuiltInTags()
{
$this->expectException('Symfony\Component\Yaml\Exception\ParseException');
$this->expectExceptionMessage('The built-in tag "!!foo" is not implemented at line 1 (near "!!foo").');