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.
+