diff --git a/CHANGELOG-4.4.md b/CHANGELOG-4.4.md index 9c685daa837a5..c16001b9e6c21 100644 --- a/CHANGELOG-4.4.md +++ b/CHANGELOG-4.4.md @@ -7,6 +7,16 @@ in 4.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/v4.4.0...v4.4.1 +* 4.4.47 (2022-10-12) + + * bug #47621 [Serializer] Allow getting discriminated type by class name (TamasSzigeti) + * bug #47808 [HttpClient] Fix seeking in not-yet-initialized requests (nicolas-grekas) + * bug #47702 [Messenger] Fix default serializer not handling DateTime objects properly (barton-webwings) + * bug #47779 [Console] Fix `Helper::removeDecoration` hyperlink bug (greew) + * bug #47763 [PropertyInfo] a readonly property must not be reported as being writable (xabbuh) + * bug #47731 [WebProfiler] Fix overflow issue in Forms panel (zolikonta) + * bug #47746 [HttpFoundation] Fix BinaryFileResponse content type detection logic (X-Coder264) + * 4.4.46 (2022-09-30) * bug #47547 [Ldap] Do not run ldap_set_option on failed connection (tatankat) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d652d3de50a5c..baf049c540d1d 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -90,21 +90,21 @@ The Symfony Connect username in parenthesis allows to get more information - Florin Patan (florinpatan) - Peter Rehm (rpet) - Henrik Bjørnskov (henrikbjorn) + - David Buchmann (dbu) - Konstantin Myakshin (koc) - Andrej Hudec (pulzarraider) - Julien Falque (julienfalque) - Massimiliano Arione (garak) - Douglas Greenshields (shieldo) - - David Buchmann (dbu) - Christian Raue - Jáchym Toušek (enumag) + - Mathias Arlaud (mtarld) - Graham Campbell (graham) - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Issei Murasawa (issei_m) - Fran Moreno (franmomu) - Malte Schlüter (maltemaltesich) - - Mathias Arlaud (mtarld) - Vasilij Dusko - Denis (yethee) - Arnout Boks (aboks) @@ -122,12 +122,12 @@ The Symfony Connect username in parenthesis allows to get more information - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) + - Antoine Lamirault - Daniel Holmes (dholmes) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - Smaine Milianni (ismail1432) - - Antoine Lamirault - John Wards (johnwards) - Dariusz Ruminski - Lars Strojny (lstrojny) @@ -210,6 +210,7 @@ The Symfony Connect username in parenthesis allows to get more information - Martin Hujer (martinhujer) - Wouter J - Guilliam Xavier + - Antonio Pauletich (x-coder264) - Timo Bakx (timobakx) - Juti Noppornpitak (shiroyuki) - Joe Bennett (kralos) @@ -226,7 +227,6 @@ The Symfony Connect username in parenthesis allows to get more information - Arnaud Kleinpeter (nanocom) - Guilherme Blanco (guilhermeblanco) - Chi-teck - - Antonio Pauletich (x-coder264) - Michael Voříšek - SpacePossum - Pablo Godel (pgodel) @@ -479,6 +479,7 @@ The Symfony Connect username in parenthesis allows to get more information - Quynh Xuan Nguyen (seriquynh) - Ray - Philipp Cordes (corphi) + - Andrii Dembitskyi - Chekote - bhavin (bhavin4u) - Pavel Popov (metaer) @@ -575,7 +576,6 @@ The Symfony Connect username in parenthesis allows to get more information - Adrian Rudnik (kreischweide) - Pavel Batanov (scaytrase) - Francesc Rosàs (frosas) - - Andrii Dembitskyi - Bongiraud Dominique - janschoenherr - Marko Kaznovac (kaznovac) @@ -642,6 +642,7 @@ The Symfony Connect username in parenthesis allows to get more information - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) - Gyula Sallai (salla) + - Stefan Gehrig (sgehrig) - Benjamin Cremer (bcremer) - rtek - Inal DJAFAR (inalgnu) @@ -870,7 +871,6 @@ The Symfony Connect username in parenthesis allows to get more information - Dirk Pahl (dirkaholic) - Cédric Lombardot (cedriclombardot) - Jonas Flodén (flojon) - - Stefan Gehrig (sgehrig) - Adrien Lucas (adrienlucas) - Dominik Zogg - Kai Dederichs @@ -1037,6 +1037,7 @@ The Symfony Connect username in parenthesis allows to get more information - Quentin Dequippe (qdequippe) - Yewhen Khoptynskyi (khoptynskyi) - Jérôme Nadaud (jnadaud) + - wuchen90 - Alexandre Tranchant (alexandre_t) - Anthony Moutte - shreyadenny @@ -1050,6 +1051,7 @@ The Symfony Connect username in parenthesis allows to get more information - Grégoire Hébert (gregoirehebert) - alcaeus - Fred Cox + - Matheo Daninos (mathdns) - Iliya Miroslavov Iliev (i.miroslavov) - Safonov Nikita (ns3777k) - Simon DELICATA @@ -1975,7 +1977,6 @@ The Symfony Connect username in parenthesis allows to get more information - Kirill Nesmeyanov (serafim) - Reece Fowell (reecefowell) - Guillaume Gammelin - - wuchen90 - Valérian Galliat - d-ph - Renan Taranto (renan-taranto) @@ -2051,6 +2052,7 @@ The Symfony Connect username in parenthesis allows to get more information - boite - Silvio Ginter - MGDSoft + - joris - Vadim Tyukov (vatson) - David Wolter (davewww) - Sortex @@ -2099,6 +2101,7 @@ The Symfony Connect username in parenthesis allows to get more information - Thomas - Norbert Schultheisz - Maximilian Berghoff (electricmaxxx) + - SOEDJEDE Felix (fsoedjede) - Piotr Antosik (antek88) - Nacho Martin (nacmartin) - Sergey Novikov (s12v) @@ -2225,6 +2228,7 @@ The Symfony Connect username in parenthesis allows to get more information - Nicolas Fabre (nfabre) - Raul Rodriguez (raul782) - mshavliuk + - Jesper Skytte - MightyBranch - Kacper Gunia (cakper) - Derek Lambert (dlambert) @@ -2413,6 +2417,7 @@ The Symfony Connect username in parenthesis allows to get more information - Daniel González Zaballos (dem3trio) - Emmanuel Vella (emmanuel.vella) - Guillaume BRETOU (guiguiboy) + - Ibon Conesa (ibonkonesa) - nuryagdy mustapayev (nueron) - Carsten Nielsen (phreaknerd) - Jay Severson @@ -2598,6 +2603,7 @@ The Symfony Connect username in parenthesis allows to get more information - Andrew Coulton - Ulugbek Miniyarov - Jeremy Benoist + - sdrewergutland - Michal Gebauer - Phil Davis - Gleb Sidora @@ -2635,6 +2641,7 @@ The Symfony Connect username in parenthesis allows to get more information - Mike Francis - Nil Borodulia - Almog Baku (almogbaku) + - Benjamin Schultz (bschultz) - Gerd Christian Kunze (derdu) - Ionel Scutelnicu (ionelscutelnicu) - Kamil Madejski (kmadejski) @@ -2801,6 +2808,7 @@ The Symfony Connect username in parenthesis allows to get more information - David Christmann - root - pf + - Zoli Konta - Vincent Chalnot - Patrizio Bekerle - Tom Maguire @@ -2917,7 +2925,6 @@ The Symfony Connect username in parenthesis allows to get more information - Kevin Verschaeve (keversc) - Kevin Herrera (kherge) - Luis Ramón López López (lrlopez) - - Matheo Daninos (mathdns) - Mehdi Mabrouk (mehdidev) - Bart Reunes (metalarend) - Muriel (metalmumu) @@ -2936,6 +2943,7 @@ The Symfony Connect username in parenthesis allows to get more information - Lajos Veres (vlajos) - Vladimir Chernyshev (volch) - Yorkie Chadwick (yorkie76) + - Pavel Barton - GuillaumeVerdon - ureimers - akimsko @@ -3203,6 +3211,7 @@ The Symfony Connect username in parenthesis allows to get more information - emilienbouard (neime) - Nicholas Byfleet (nickbyfleet) - Nicolas Bondoux (nsbx) + - Cedric Kastner (nurtext) - ollie harridge (ollietb) - Pawel Szczepanek (pauluz) - Philippe Degeeter (pdegeeter) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php index fe776b90d3df1..ca79f45ac9985 100644 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php @@ -12,6 +12,10 @@ // Please update when phpunit needs to be reinstalled with fresh deps: // Cache-Id: 2021-02-04 11:00 UTC +if ('cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + error_reporting(-1); global $argv, $argc; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php b/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php index ec9ae1f97c0ff..024ba08d9551b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/bin/check-unused-known-tags.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + require dirname(__DIR__, 6).'/vendor/autoload.php'; use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\UnusedTagsPassUtils; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig index db97100e49b37..d99ad4f77946b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig @@ -90,7 +90,8 @@ cursor: pointer; padding: 5px 7px 5px 22px; position: relative; - + overflow: hidden; + text-overflow: ellipsis; } .tree .toggle-button { /* provide a bigger clickable area than just 10x10px */ @@ -449,7 +450,7 @@ {% import _self as tree %} {% set has_error = data.errors is defined and data.errors|length > 0 %}
  • -
    +
    {% if has_error %}
    {{ data.errors|length }}
    {% endif %} diff --git a/src/Symfony/Component/Console/Helper/Helper.php b/src/Symfony/Component/Console/Helper/Helper.php index 0521aaf7d2933..18d85b94073e0 100644 --- a/src/Symfony/Component/Console/Helper/Helper.php +++ b/src/Symfony/Component/Console/Helper/Helper.php @@ -135,6 +135,8 @@ public static function removeDecoration(OutputFormatterInterface $formatter, $st $string = $formatter->format($string); // remove already formatted characters $string = preg_replace("/\033\[[^m]*m/", '', $string); + // remove terminal hyperlinks + $string = preg_replace('/\\033]8;[^;]*;[^\\033]*\\033\\\\/', '', $string); $formatter->setDecorated($isDecorated); return $string; diff --git a/src/Symfony/Component/Console/Tests/Helper/HelperTest.php b/src/Symfony/Component/Console/Tests/Helper/HelperTest.php index 184d86e092aba..b8c8910874ed8 100644 --- a/src/Symfony/Component/Console/Tests/Helper/HelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/HelperTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Console\Tests\Helper; use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\Helper; class HelperTest extends TestCase @@ -42,6 +43,16 @@ public function formatTimeProvider() ]; } + public function decoratedTextProvider() + { + return [ + ['abc', 'abc'], + ['abc', 'abc'], + ["a\033[1;36mbc", 'abc'], + ["a\033]8;;http://url\033\\b\033]8;;\033\\c", 'abc'], + ]; + } + /** * @dataProvider formatTimeProvider * @@ -52,4 +63,12 @@ public function testFormatTime($secs, $expectedFormat) { $this->assertEquals($expectedFormat, Helper::formatTime($secs)); } + + /** + * @dataProvider decoratedTextProvider + */ + public function testRemoveDecoration(string $decoratedText, string $undecoratedText) + { + $this->assertEquals($undecoratedText, Helper::removeDecoration(new OutputFormatter(), $decoratedText)); + } } diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index c0f3f96b2aa95..0e3f30cdadadf 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -1388,6 +1388,31 @@ public function testWithColspanAndMaxWith() | | | nsectetur | +-----------------+-----------------+-----------------+ +TABLE; + + $this->assertSame($expected, $this->getOutputContent($output)); + } + + public function testWithHyperlinkAndMaxWidth() + { + $table = new Table($output = $this->getOutputStream(true)); + $table + ->setRows([ + ['Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor'], + ]) + ; + $table->setColumnMaxWidth(0, 20); + $table->render(); + + $expected = + <<assertSame($expected, $this->getOutputContent($output)); diff --git a/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php b/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php index c86e962526182..72b4d25f56d4f 100644 --- a/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php +++ b/src/Symfony/Component/ExpressionLanguage/Resources/bin/generate_operator_regex.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + $operators = ['not', '!', 'or', '||', '&&', 'and', '|', '^', '&', '==', '===', '!=', '!==', '<', '>', '>=', '<=', 'not in', 'in', '..', '+', '-', '~', '*', '/', '%', 'matches', '**']; $operators = array_combine($operators, array_map('strlen', $operators)); arsort($operators); diff --git a/src/Symfony/Component/HttpClient/Response/StreamWrapper.php b/src/Symfony/Component/HttpClient/Response/StreamWrapper.php index 6bb31687b949c..989dc90c6d498 100644 --- a/src/Symfony/Component/HttpClient/Response/StreamWrapper.php +++ b/src/Symfony/Component/HttpClient/Response/StreamWrapper.php @@ -22,7 +22,7 @@ */ class StreamWrapper { - /** @var resource|string|null */ + /** @var resource|null */ public $context; /** @var HttpClientInterface */ @@ -31,7 +31,7 @@ class StreamWrapper /** @var ResponseInterface */ private $response; - /** @var resource|null */ + /** @var resource|string|null */ private $content; /** @var resource|null */ @@ -81,6 +81,7 @@ public function bindHandles(&$handle, &$content): void { $this->handle = &$handle; $this->content = &$content; + $this->offset = null; } public function stream_open(string $path, string $mode, int $options): bool @@ -125,7 +126,7 @@ public function stream_read(int $count) } } - if (0 !== fseek($this->content, $this->offset)) { + if (0 !== fseek($this->content, $this->offset ?? 0)) { return false; } @@ -154,6 +155,11 @@ public function stream_read(int $count) try { $this->eof = true; $this->eof = !$chunk->isTimeout(); + + if (!$this->eof && !$this->blocking) { + return ''; + } + $this->eof = $chunk->isLast(); if ($chunk->isFirst()) { @@ -196,7 +202,7 @@ public function stream_set_option(int $option, int $arg1, ?int $arg2): bool public function stream_tell(): int { - return $this->offset; + return $this->offset ?? 0; } public function stream_eof(): bool @@ -206,6 +212,11 @@ public function stream_eof(): bool public function stream_seek(int $offset, int $whence = \SEEK_SET): bool { + if (null === $this->content && null === $this->offset) { + $this->response->getStatusCode(); + $this->offset = 0; + } + if (!\is_resource($this->content) || 0 !== fseek($this->content, 0, \SEEK_END)) { return false; } @@ -213,7 +224,7 @@ public function stream_seek(int $offset, int $whence = \SEEK_SET): bool $size = ftell($this->content); if (\SEEK_CUR === $whence) { - $offset += $this->offset; + $offset += $this->offset ?? 0; } if (\SEEK_END === $whence || $size < $offset) { diff --git a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php index d36e7f70b72ca..3cb7d5d48f926 100644 --- a/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php +++ b/src/Symfony/Component/HttpClient/Tests/HttpClientTestCase.php @@ -118,6 +118,18 @@ public function testNonBlockingStream() $this->assertTrue(feof($stream)); } + public function testSeekAsyncStream() + { + $client = $this->getHttpClient(__FUNCTION__); + $response = $client->request('GET', 'http://localhost:8057/timeout-body'); + $stream = $response->toStream(false); + + $this->assertSame(0, fseek($stream, 0, \SEEK_CUR)); + $this->assertSame('<1>', fread($stream, 8192)); + $this->assertFalse(feof($stream)); + $this->assertSame('<2>', stream_get_contents($stream)); + } + public function testTimeoutIsNotAFatalError() { $client = $this->getHttpClient(__FUNCTION__); diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php index 4e8dbf26d7e29..42accfdf7f713 100644 --- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php @@ -311,6 +311,7 @@ protected function getHttpClient(string $testCase): HttpClientInterface return $client; case 'testNonBlockingStream': + case 'testSeekAsyncStream': $responses[] = new MockResponse((function () { yield '<1>'; yield ''; yield '<2>'; })(), ['response_headers' => $headers]); break; diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 2cd105c3bb0f3..1842256a3f01c 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -201,9 +201,9 @@ public function setContentDisposition($disposition, $filename = '', $filenameFal */ public function prepare(Request $request) { - parent::prepare($request); - if ($this->isInformational() || $this->isEmpty()) { + parent::prepare($request); + $this->maxlen = 0; return $this; @@ -213,6 +213,8 @@ public function prepare(Request $request) $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); } + parent::prepare($request); + $this->offset = 0; $this->maxlen = -1; diff --git a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php index 4e4ddbf4446ef..0539f74e9982c 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Tests; use Symfony\Component\HttpFoundation\BinaryFileResponse; +use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\Stream; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\ResponseHeaderBag; @@ -388,6 +389,40 @@ public function testPrepareNotAddingContentTypeHeaderIfNoContentResponse() $this->assertFalse($response->headers->has('Content-Type')); } + public function testContentTypeIsCorrectlyDetected() + { + $file = new File(__DIR__.'/File/Fixtures/test.gif'); + + try { + $file->getMimeType(); + } catch (\LogicException $e) { + $this->markTestSkipped('Guessing the mime type is not possible'); + } + + $response = new BinaryFileResponse($file); + + $request = Request::create('/'); + $response->prepare($request); + + $this->assertSame(200, $response->getStatusCode()); + $this->assertSame('image/gif', $response->headers->get('Content-Type')); + } + + public function testContentTypeIsNotGuessedWhenTheFileWasNotModified() + { + $response = new BinaryFileResponse(__DIR__.'/File/Fixtures/test.gif'); + $response->setAutoLastModified(); + + $request = Request::create('/'); + $request->headers->set('If-Modified-Since', $response->getLastModified()->format('D, d M Y H:i:s').' GMT'); + $isNotModified = $response->isNotModified($request); + $this->assertTrue($isNotModified); + $response->prepare($request); + + $this->assertSame(304, $response->getStatusCode()); + $this->assertFalse($response->headers->has('Content-Type')); + } + protected function provideResponse() { return new BinaryFileResponse(__DIR__.'/../README.md', 200, ['Content-Type' => 'application/octet-stream']); diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index c6476b615d29a..f944b3d9e6ac6 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -76,11 +76,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private static $freshCache = []; - public const VERSION = '4.4.46'; - public const VERSION_ID = 40446; + public const VERSION = '4.4.47'; + public const VERSION_ID = 40447; public const MAJOR_VERSION = 4; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 46; + public const RELEASE_VERSION = 47; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2022'; diff --git a/src/Symfony/Component/Intl/Resources/bin/common.php b/src/Symfony/Component/Intl/Resources/bin/common.php index cf47fa448b034..89d3459143d96 100644 --- a/src/Symfony/Component/Intl/Resources/bin/common.php +++ b/src/Symfony/Component/Intl/Resources/bin/common.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + define('LINE_WIDTH', 75); define('LINE', str_repeat('-', LINE_WIDTH)."\n"); diff --git a/src/Symfony/Component/Intl/Resources/bin/update-data.php b/src/Symfony/Component/Intl/Resources/bin/update-data.php index 4fc4b2c13a5c9..95a85b4cb3db6 100644 --- a/src/Symfony/Component/Intl/Resources/bin/update-data.php +++ b/src/Symfony/Component/Intl/Resources/bin/update-data.php @@ -23,6 +23,10 @@ use Symfony\Component\Intl\Locale; use Symfony\Component\Intl\Util\GitRepository; +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + require_once __DIR__.'/common.php'; require_once __DIR__.'/autoload.php'; diff --git a/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php b/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php index b5e93370027b6..3b34140cd4d05 100644 --- a/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php +++ b/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php @@ -21,6 +21,7 @@ use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Exception\ExceptionInterface; use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; +use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer as SymfonySerializer; use Symfony\Component\Serializer\SerializerInterface as SymfonySerializerInterface; @@ -50,7 +51,7 @@ public static function create(): self } $encoders = [new XmlEncoder(), new JsonEncoder()]; - $normalizers = [new ArrayDenormalizer(), new ObjectNormalizer()]; + $normalizers = [new DateTimeNormalizer(), new ArrayDenormalizer(), new ObjectNormalizer()]; $serializer = new SymfonySerializer($normalizers, $encoders); return new self($serializer); diff --git a/src/Symfony/Component/Mime/Resources/bin/update_mime_types.php b/src/Symfony/Component/Mime/Resources/bin/update_mime_types.php index 74a9449c75e8d..08c52f7d07cd7 100644 --- a/src/Symfony/Component/Mime/Resources/bin/update_mime_types.php +++ b/src/Symfony/Component/Mime/Resources/bin/update_mime_types.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + // load new map $data = file_get_contents('https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); $new = []; diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index a6e3738e7cb0c..4049d914f5df0 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -180,7 +180,7 @@ public function isReadable($class, $property, array $context = []): ?bool */ public function isWritable($class, $property, array $context = []): ?bool { - if ($this->isAllowedProperty($class, $property)) { + if ($this->isAllowedProperty($class, $property, true)) { return true; } @@ -389,11 +389,15 @@ private function isNullableProperty(string $class, string $property): bool return false; } - private function isAllowedProperty(string $class, string $property): bool + private function isAllowedProperty(string $class, string $property, bool $writeAccessRequired = false): bool { try { $reflectionProperty = new \ReflectionProperty($class, $property); + if (\PHP_VERSION_ID >= 80100 && $writeAccessRequired && $reflectionProperty->isReadOnly()) { + return false; + } + if ($this->accessFlags & self::ALLOW_PUBLIC && $reflectionProperty->isPublic()) { return true; } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php index 315171333d137..0d587a5f25a36 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php @@ -22,6 +22,7 @@ use Symfony\Component\PropertyInfo\Tests\Fixtures\Php74Dummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy; use Symfony\Component\PropertyInfo\Tests\Fixtures\Php7ParentDummy; +use Symfony\Component\PropertyInfo\Tests\Fixtures\Php81Dummy; use Symfony\Component\PropertyInfo\Type; /** @@ -234,6 +235,7 @@ public function php71TypesProvider() /** * @dataProvider php80TypesProvider + * * @requires PHP 8 */ public function testExtractPhp80Type($property, array $type = null) @@ -257,6 +259,7 @@ public function php80TypesProvider() /** * @dataProvider php81TypesProvider + * * @requires PHP 8.1 */ public function testExtractPhp81Type($property, array $type = null) @@ -272,8 +275,17 @@ public function php81TypesProvider() ]; } + /** + * @requires PHP 8.1 + */ + public function testReadonlyPropertiesAreNotWriteable() + { + $this->assertFalse($this->extractor->isWritable(Php81Dummy::class, 'foo')); + } + /** * @dataProvider php82TypesProvider + * * @requires PHP 8.2 */ public function testExtractPhp82Type($property, array $type = null) diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php index 842f59fbfd47b..13713b69dde03 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php @@ -13,6 +13,10 @@ class Php81Dummy { + public function __construct(public readonly string $foo) + { + } + public function getNothing(): never { throw new \Exception('Oops'); diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.nn.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.nn.xlf index 89ca44fa88f26..1c8e065d71d70 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.nn.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.nn.xlf @@ -70,6 +70,14 @@ Invalid or expired login link.Innloggingslenka er ugyldig eller utgjengen. + + Too many failed login attempts, please try again in %minutes% minute. + For mange mislykkede påloggingsforsøk, prøv igjen om %minutes% minutt. + + + Too many failed login attempts, please try again in %minutes% minutes. + For mange mislykkede påloggingsforsøk, prøv igjen om %minutes% minutter. + diff --git a/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorMapping.php b/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorMapping.php index 0c314c7ba455d..ffaa8eab9a8ec 100644 --- a/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorMapping.php +++ b/src/Symfony/Component/Serializer/Mapping/ClassDiscriminatorMapping.php @@ -53,7 +53,7 @@ public function getClassForType(string $type): ?string public function getMappedObjectType($object): ?string { foreach ($this->typesMapping as $type => $typeClass) { - if (is_a($object, $typeClass)) { + if (is_a($object, $typeClass, true)) { return $type; } } diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/ClassDiscriminatorMappingTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/ClassDiscriminatorMappingTest.php index aed2d221d4a10..d63fdb68bff34 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/ClassDiscriminatorMappingTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/ClassDiscriminatorMappingTest.php @@ -39,6 +39,7 @@ public function testMappedObjectType() 'third' => AbstractDummyThirdChild::class, ]); + $this->assertEquals('first', $mapping->getMappedObjectType(AbstractDummyFirstChild::class)); $this->assertEquals('first', $mapping->getMappedObjectType(new AbstractDummyFirstChild())); $this->assertNull($mapping->getMappedObjectType(new AbstractDummySecondChild())); $this->assertSame('third', $mapping->getMappedObjectType(new AbstractDummyThirdChild())); diff --git a/src/Symfony/Component/Translation/Resources/bin/translation-status.php b/src/Symfony/Component/Translation/Resources/bin/translation-status.php index fac8acbadca32..53e642c00dca7 100644 --- a/src/Symfony/Component/Translation/Resources/bin/translation-status.php +++ b/src/Symfony/Component/Translation/Resources/bin/translation-status.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +if ('cli' !== \PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + $usageInstructions = <<This value is not a valid International Securities Identification Number (ISIN). Verdien er ikkje eit gyldig International Securities Identification Number (ISIN). + + This value should be a valid expression. + Denne verdien skal være et gyldig uttrykk. + + + This value is not a valid CSS color. + Denne verdien er ikke en gyldig CSS-farge. + + + This value is not a valid CIDR notation. + Denne verdien er ikke en gyldig CIDR-notasjon. + + + The value of the netmask should be between {{ min }} and {{ max }}. + Verdien av nettmasken skal være mellom {{ min }} og {{ max }}. + diff --git a/src/Symfony/Component/VarDumper/Resources/bin/var-dump-server b/src/Symfony/Component/VarDumper/Resources/bin/var-dump-server index 98c813a0639b5..f398fcef72d39 100755 --- a/src/Symfony/Component/VarDumper/Resources/bin/var-dump-server +++ b/src/Symfony/Component/VarDumper/Resources/bin/var-dump-server @@ -10,6 +10,10 @@ * file that was distributed with this source code. */ +if ('cli' !== PHP_SAPI) { + throw new Exception('This script must be run from the command line.'); +} + /** * Starts a dump server to collect and output dumps on a single place with multiple formats support. *