diff --git a/CHANGELOG-5.4.md b/CHANGELOG-5.4.md index ef84b0a355fcf..958891879ffaf 100644 --- a/CHANGELOG-5.4.md +++ b/CHANGELOG-5.4.md @@ -7,6 +7,14 @@ in 5.4 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/v5.4.0...v5.4.1 +* 5.4.33 (2023-12-01) + + * bug #52804 [Serializer] Fix support of plain object types denormalization (andersonamuller) + * bug #52845 [Routing] Restore aliases removal in RouteCollection::remove() (fancyweb) + * bug #52846 [PhpUnitBridge]  run composer update for compatibility with PHPUnit versions shipping composer.lock (xabbuh) + * bug #52823 add parameter types in query builder (javiercno) + * bug #52806 [Routing] Fix removing aliases pointing to removed route in `RouteCollection::remove()` (fancyweb) + * 5.4.32 (2023-11-29) * bug #52786 [Serializer] Revert allowed attributes fix (mtarld) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ce074d555f730..a3e1c4ac3a9af 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -18,9 +18,9 @@ The Symfony Connect username in parenthesis allows to get more information - Jordi Boggiano (seldaek) - Maxime Steinhausser (ogizanagi) - Kévin Dunglas (dunglas) + - Alexandre Daubois (alexandre-daubois) - Victor Berchet (victor) - Ryan Weaver (weaverryan) - - Alexandre Daubois (alexandre-daubois) - Javier Eguiluz (javier.eguiluz) - Jérémy DERUSSÉ (jderusse) - Roland Franssen @@ -33,8 +33,8 @@ The Symfony Connect username in parenthesis allows to get more information - Hugo Hamon (hhamon) - Tobias Nyholm (tobias) - Samuel ROZE (sroze) - - Pascal Borreli (pborreli) - Jérôme Tamarelle (gromnan) + - Pascal Borreli (pborreli) - Romain Neutron - Antoine Lamirault (alamirault) - Joseph Bielawski (stloyd) @@ -90,9 +90,9 @@ The Symfony Connect username in parenthesis allows to get more information - Vladimir Reznichenko (kalessil) - Peter Rehm (rpet) - Henrik Bjørnskov (henrikbjorn) + - Mathias Arlaud (mtarld) - Andrej Hudec (pulzarraider) - Jáchym Toušek (enumag) - - Mathias Arlaud (mtarld) - David Buchmann (dbu) - Dariusz Ruminski - Christian Raue @@ -101,11 +101,11 @@ The Symfony Connect username in parenthesis allows to get more information - Michel Weimerskirch (mweimerskirch) - Issei Murasawa (issei_m) - Douglas Greenshields (shieldo) + - Frank A. Fiebig (fafiebig) + - Baldini - Alex Pott - Fran Moreno (franmomu) - Arnout Boks (aboks) - - Frank A. Fiebig (fafiebig) - - Baldini - Charles Sarrazin (csarrazi) - Ruud Kamphuis (ruudk) - Henrik Westphal (snc) @@ -149,21 +149,21 @@ The Symfony Connect username in parenthesis allows to get more information - Rokas Mikalkėnas (rokasm) - Lars Strojny (lstrojny) - lenar + - Vladimir Tsykun (vtsykun) - Jacob Dreesen (jdreesen) + - Tac Tacelosky (tacman1123) - Włodzimierz Gajda (gajdaw) - Adrien Brault (adrienbrault) - - Tac Tacelosky (tacman1123) - Théo FIDRY - Florian Voutzinos (florianv) - Teoh Han Hui (teohhanhui) - Przemysław Bogusz (przemyslaw-bogusz) - Colin Frei + - Martin Auswöger - Javier Spagnoletti (phansys) - excelwebzone - - Vladimir Tsykun (vtsykun) - Paráda József (paradajozsef) - Baptiste Clavié (talus) - - Martin Auswöger - Alexander Schwenn (xelaris) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) @@ -319,6 +319,7 @@ The Symfony Connect username in parenthesis allows to get more information - Pierre Minnieur (pminnieur) - Dominique Bongiraud - Hugo Monteiro (monteiro) + - Bram Leeda (bram123) - Timo Bakx (timobakx) - Dmitrii Poddubnyi (karser) - Julien Pauli @@ -365,7 +366,6 @@ The Symfony Connect username in parenthesis allows to get more information - Florent Morselli (spomky_) - dFayet - Rob Frawley 2nd (robfrawley) - - Bram Leeda (bram123) - Nikita Konstantinov (unkind) - Dariusz - Francois Zaninotto @@ -405,6 +405,7 @@ The Symfony Connect username in parenthesis allows to get more information - Eugene Leonovich (rybakit) - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) + - Marvin Petker - GordonsLondon - Ray - Philipp Cordes (corphi) @@ -426,6 +427,7 @@ The Symfony Connect username in parenthesis allows to get more information - Matthieu Auger (matthieuauger) - Sergey Belyshkin (sbelyshkin) - Kévin THERAGE (kevin_therage) + - Herberto Graca - Yoann RENARD (yrenard) - Josip Kruslin (jkruslin) - Daniel Gorgan @@ -474,7 +476,6 @@ The Symfony Connect username in parenthesis allows to get more information - Warxcell (warxcell) - Atsuhiro KUBO (iteman) - rudy onfroy (ronfroy) - - Marvin Petker - Serkan Yildiz (srknyldz) - Andrew Moore (finewolf) - Bertrand Zuchuat (garfield-fr) @@ -493,6 +494,7 @@ The Symfony Connect username in parenthesis allows to get more information - Aurelijus Valeiša (aurelijus) - Jan Decavele (jandc) - Gustavo Piltcher + - Evert Harmeling (evertharmeling) - Lee Rowlands - Stepan Tanasiychuk (stfalcon) - Ivan Kurnosov @@ -517,7 +519,6 @@ The Symfony Connect username in parenthesis allows to get more information - Ahmed Raafat - Philippe Segatori - Thibaut Cheymol (tcheymol) - - Herberto Graca - Erin Millard - Matthew Lewinski (lewinski) - Islam Israfilov (islam93) @@ -600,7 +601,6 @@ The Symfony Connect username in parenthesis allows to get more information - Matthias Althaus (althaus) - Saif Eddin G - Endre Fejes - - Evert Harmeling (evertharmeling) - Tobias Naumann (tna) - Daniel Beyer - flack (flack) @@ -804,6 +804,7 @@ The Symfony Connect username in parenthesis allows to get more information - Greg ORIOL - Jakub Škvára (jskvara) - Andrew Udvare (audvare) + - Ivan Sarastov (isarastov) - siganushka (siganushka) - alexpods - Adam Szaraniec @@ -1313,7 +1314,6 @@ The Symfony Connect username in parenthesis allows to get more information - Gerard van Helden (drm) - Florent Destremau (florentdestremau) - Florian Wolfsjaeger (flowolf) - - Ivan Sarastov (isarastov) - Johnny Peck (johnnypeck) - Jordi Sala Morales (jsala) - Sander De la Marche (sanderdlm) @@ -3043,6 +3043,7 @@ The Symfony Connect username in parenthesis allows to get more information - Olivier Laviale (olvlvl) - Pierre Gasté (pierre_g) - Pablo Monterde Perez (plebs) + - Jakub Podhorsky (podhy) - Pierre-Olivier Vares (povares) - Jimmy Leger (redpanda) - Ronny López (ronnylt) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index bc251877d7cdf..816e8d9c2158c 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -262,7 +262,7 @@ putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99"); $q = '\\' === \DIRECTORY_SEPARATOR && \PHP_VERSION_ID < 80000 ? '"' : ''; // --no-suggest is not in the list to keep compat with composer 1.0, which is shipped with Ubuntu 16.04LTS - $exit = proc_close(proc_open("$q$COMPOSER install --no-dev --prefer-dist --no-progress $q", [], $p, getcwd())); + $exit = proc_close(proc_open("$q$COMPOSER update --no-dev --prefer-dist --no-progress $q", [], $p, getcwd())); putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); if ($prevCacheDir) { putenv("COMPOSER_CACHE_DIR=$prevCacheDir"); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services14.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services14.xml index bad2ec0ab377c..cc0310ceb2931 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services14.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services14.xml @@ -3,10 +3,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> - - app - - diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index 32bf613037992..b892a1c34ea6e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; +use Symfony\Component\Intl\Intl; use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException; @@ -90,6 +91,10 @@ public function testSubmitFromSingleTextDateTime() // we test against "de_DE", so we need the full implementation IntlTestHelper::requireFullIntl($this, false); + if ('71.1' === Intl::getIcuVersion()) { + $this->markTestSkipped('Skipping test due to a bug in ICU 71.1.'); + } + \Locale::setDefault('de_DE'); $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -112,6 +117,10 @@ public function testSubmitFromSingleTextDateTimeImmutable() // we test against "de_DE", so we need the full implementation IntlTestHelper::requireFullIntl($this, false); + if ('71.1' === Intl::getIcuVersion()) { + $this->markTestSkipped('Skipping test due to a bug in ICU 71.1.'); + } + \Locale::setDefault('de_DE'); $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -135,6 +144,10 @@ public function testSubmitFromSingleTextString() // we test against "de_DE", so we need the full implementation IntlTestHelper::requireFullIntl($this, false); + if ('71.1' === Intl::getIcuVersion()) { + $this->markTestSkipped('Skipping test due to a bug in ICU 71.1.'); + } + \Locale::setDefault('de_DE'); $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -157,6 +170,10 @@ public function testSubmitFromSingleTextTimestamp() // we test against "de_DE", so we need the full implementation IntlTestHelper::requireFullIntl($this, false); + if ('71.1' === Intl::getIcuVersion()) { + $this->markTestSkipped('Skipping test due to a bug in ICU 71.1.'); + } + \Locale::setDefault('de_DE'); $form = $this->factory->create(static::TESTED_TYPE, null, [ @@ -181,6 +198,10 @@ public function testSubmitFromSingleTextRaw() // we test against "de_DE", so we need the full implementation IntlTestHelper::requireFullIntl($this, false); + if ('71.1' === Intl::getIcuVersion()) { + $this->markTestSkipped('Skipping test due to a bug in ICU 71.1.'); + } + \Locale::setDefault('de_DE'); $form = $this->factory->create(static::TESTED_TYPE, null, [ diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index c4675f51ef41c..3cfc3af9a066c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -78,11 +78,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static $freshCache = []; - public const VERSION = '5.4.32'; - public const VERSION_ID = 50432; + public const VERSION = '5.4.33'; + public const VERSION_ID = 50433; public const MAJOR_VERSION = 5; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 32; + public const RELEASE_VERSION = 33; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2024'; diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php index 875f985cd038b..bb322e760fbdb 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php @@ -182,7 +182,7 @@ public function get(): ?array if ($this->driverConnection->getDatabasePlatform() instanceof OraclePlatform) { $query = $this->createQueryBuilder('w') ->where('w.id IN ('.str_replace('SELECT a.* FROM', 'SELECT a.id FROM', $sql).')') - ->setParameters($query->getParameters()); + ->setParameters($query->getParameters(), $query->getParameterTypes()); if (method_exists(QueryBuilder::class, 'forUpdate')) { $query->forUpdate(); diff --git a/src/Symfony/Component/Routing/RouteCollection.php b/src/Symfony/Component/Routing/RouteCollection.php index a0700bba3d681..b1219f844b7c0 100644 --- a/src/Symfony/Component/Routing/RouteCollection.php +++ b/src/Symfony/Component/Routing/RouteCollection.php @@ -157,9 +157,24 @@ public function get(string $name) */ public function remove($name) { + $routes = []; foreach ((array) $name as $n) { + if (isset($this->routes[$n])) { + $routes[] = $n; + } + unset($this->routes[$n], $this->priorities[$n], $this->aliases[$n]); } + + if (!$routes) { + return; + } + + foreach ($this->aliases as $k => $alias) { + if (\in_array($alias->getId(), $routes, true)) { + unset($this->aliases[$k]); + } + } } /** diff --git a/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php b/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php index a191c88a61849..7625bcf54ebdb 100644 --- a/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php @@ -219,17 +219,22 @@ public function testGet() public function testRemove() { $collection = new RouteCollection(); - $collection->add('foo', $foo = new Route('/foo')); + $collection->add('foo', new Route('/foo')); $collection1 = new RouteCollection(); $collection1->add('bar', $bar = new Route('/bar')); $collection->addCollection($collection1); $collection->add('last', $last = new Route('/last')); + $collection->addAlias('alias_removed_when_removing_route_foo', 'foo'); + $collection->addAlias('alias_directly_removed', 'bar'); $collection->remove('foo'); $this->assertSame(['bar' => $bar, 'last' => $last], $collection->all(), '->remove() can remove a single route'); + $collection->remove('alias_directly_removed'); + $this->assertNull($collection->getAlias('alias_directly_removed')); $collection->remove(['bar', 'last']); $this->assertSame([], $collection->all(), '->remove() accepts an array and can remove multiple routes at once'); + $this->assertNull($collection->getAlias('alias_removed_when_removing_route_foo')); } public function testSetHost() diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 732586bd85f9b..79ede1a90e698 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -584,7 +584,7 @@ private function validateAndDenormalize(array $types, string $currentClass, stri $expectedTypes[Type::BUILTIN_TYPE_OBJECT === $builtinType && $class ? $class : $builtinType] = true; - if (Type::BUILTIN_TYPE_OBJECT === $builtinType) { + if (Type::BUILTIN_TYPE_OBJECT === $builtinType && null !== $class) { if (!$this->serializer instanceof DenormalizerInterface) { throw new LogicException(sprintf('Cannot denormalize attribute "%s" for class "%s" because injected serializer is not a denormalizer.', $attribute, $class)); } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 35616b658ba78..4e781c5d81175 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -113,6 +113,17 @@ public function testDenormalizeWithExtraAttributesAndNoGroupsWithMetadataFactory ); } + public function testDenormalizePlainObject() + { + $extractor = new PhpDocExtractor(); + $normalizer = new ObjectNormalizer(null, null, null, $extractor); + $dummy = $normalizer->denormalize(['plainObject' => (object) ['foo' => 'bar']], DummyWithPlainObject::class); + + $this->assertInstanceOf(DummyWithPlainObject::class, $dummy); + $this->assertInstanceOf(\stdClass::class, $dummy->plainObject); + $this->assertSame('bar', $dummy->plainObject->foo); + } + public function testDenormalizeCollectionDecodedFromXmlWithOneChild() { $denormalizer = $this->getDenormalizerForDummyCollection(); @@ -598,6 +609,12 @@ protected function setAttributeValue(object $object, string $attribute, $value, } } +class DummyWithPlainObject +{ + /** @var object */ + public $plainObject; +} + class ObjectWithBasicProperties { /** @var bool */