Skip to content

Commit db5ef7f

Browse files
committed
Merge branch '6.4' into 7.0
* 6.4: (23 commits) fix merge add missing return type-hints fix merge explicitly mark nullable parameters as nullable fix low deps tests [HttpKernel] Fix datacollector caster for reference object property [Serializer] Fixing PHP warning in the ObjectNormalizer with MaxDepth enabled bug symfony#51578 [Cache] always select database for persistent redis connections [Security] Validate that CSRF token in form login is string similar to username/password [Serializer] Use explicit nullable type [validator] validated Dutch translation Improve dutch translations [Translation] Skip state=needs-translation entries only when source == target [HttpKernel] Ensure controllers are not lazy [Validator] Fill in trans-unit id 113: This URL does not contain a TLD. [Validator] added missing Polish translation for unit 113 [Validator] add missing lv translation [HttpClient] Let curl handle transfer encoding [Messenger] Make Doctrine connection ignore unrelated tables on setup [HttpFoundation] Set content-type header in RedirectResponse ...
2 parents bb4854c + ba6a65c commit db5ef7f

File tree

86 files changed

+727
-56
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+727
-56
lines changed

.github/sync-translations.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ function mergeDom(\DOMDocument $dom, \DOMNode $tree, \DOMNode $input)
108108
if ($catalogue->defines($resname, $domain)) {
109109
$translation = $catalogue->get($resname, $domain);
110110
$metadata = $catalogue->getMetadata($resname, $domain);
111+
} else {
112+
$translation = $source;
111113
}
112114
$metadata['id'] = $enCatalogue->getMetadata($resname, $domain)['id'];
113115
if ($resname !== $source) {

.github/workflows/integration-tests.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ jobs:
124124
steps:
125125
- name: Checkout
126126
uses: actions/checkout@v4
127+
with:
128+
fetch-depth: 0
127129

128130
- name: Install system dependencies
129131
run: |
@@ -218,13 +220,11 @@ jobs:
218220
- name: Check for changes in translation files
219221
id: changed-translation-files
220222
run: |
221-
if git diff --quiet HEAD~1 HEAD -- 'src/**/Resources/translations/*.xlf'; then
222-
echo "{changed}={true}" >> $GITHUB_OUTPUT
223-
else
224-
echo "{changed}={false}" >> $GITHUB_OUTPUT
225-
fi
223+
echo 'changed='$((git diff --quiet HEAD~1 HEAD -- 'src/**/Resources/translations/*.xlf' || (echo 'true' && exit 1)) && echo 'false') >> $GITHUB_OUTPUT
226224
227225
- name: Check Translation Status
228226
if: steps.changed-translation-files.outputs.changed == 'true'
229227
run: |
230228
php src/Symfony/Component/Translation/Resources/bin/translation-status.php -v
229+
php .github/sync-translations.php
230+
git diff --exit-code src/ || (echo 'Run "php .github/sync-translations.php" to fix XLIFF files.' && exit 1)

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
14811481
$defaultDir = $container->getParameterBag()->resolveValue($config['default_path']);
14821482
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
14831483
if ($container->fileExists($dir = $bundle['path'].'/Resources/translations') || $container->fileExists($dir = $bundle['path'].'/translations')) {
1484-
$dirs[] = $dir;
1484+
$dirs[] = $transPaths[] = $dir;
14851485
} else {
14861486
$nonExistingDirs[] = $dir;
14871487
}

src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@
138138
service('property_info')->ignoreOnInvalid(),
139139
service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(),
140140
null,
141+
[],
142+
service('property_info')->ignoreOnInvalid(),
141143
])
142144

143145
->set('serializer.denormalizer.array', ArrayDenormalizer::class)

src/Symfony/Component/Cache/Tests/Traits/RedisTraitTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,57 @@ public static function provideCreateConnection(): array
7373
],
7474
];
7575
}
76+
77+
/**
78+
* Due to a bug in phpredis, the persistent connection will keep its last selected database. So when re-using
79+
* a persistent connection, the database has to be re-selected, too.
80+
*
81+
* @see https://github.com/phpredis/phpredis/issues/1920
82+
*
83+
* @group integration
84+
*/
85+
public function testPconnectSelectsCorrectDatabase()
86+
{
87+
if (!class_exists(\Redis::class)) {
88+
throw new SkippedTestSuiteError('The "Redis" class is required.');
89+
}
90+
if (!getenv('REDIS_HOST')) {
91+
throw new SkippedTestSuiteError('REDIS_HOST env var is not defined.');
92+
}
93+
if (!\ini_get('redis.pconnect.pooling_enabled')) {
94+
throw new SkippedTestSuiteError('The bug only occurs when pooling is enabled.');
95+
}
96+
97+
// Limit the connection pool size to 1:
98+
if (false === $prevPoolSize = ini_set('redis.pconnect.connection_limit', 1)) {
99+
throw new SkippedTestSuiteError('Unable to set pool size');
100+
}
101+
102+
try {
103+
$mock = self::getObjectForTrait(RedisTrait::class);
104+
105+
$dsn = 'redis://'.getenv('REDIS_HOST');
106+
107+
$cacheKey = 'testPconnectSelectsCorrectDatabase';
108+
$cacheValueOnDb1 = 'I should only be on database 1';
109+
110+
// First connect to database 1 and set a value there so we can identify this database:
111+
$db1 = $mock::createConnection($dsn, ['dbindex' => 1, 'persistent' => 1]);
112+
self::assertInstanceOf(\Redis::class, $db1);
113+
self::assertSame(1, $db1->getDbNum());
114+
$db1->set($cacheKey, $cacheValueOnDb1);
115+
self::assertSame($cacheValueOnDb1, $db1->get($cacheKey));
116+
117+
// Unset the connection - do not use `close()` or we will lose the persistent connection:
118+
unset($db1);
119+
120+
// Now connect to database 0 and see that we do not actually ended up on database 1 by checking the value:
121+
$db0 = $mock::createConnection($dsn, ['dbindex' => 0, 'persistent' => 1]);
122+
self::assertInstanceOf(\Redis::class, $db0);
123+
self::assertSame(0, $db0->getDbNum()); // Redis is lying here! We could actually be on any database!
124+
self::assertNotSame($cacheValueOnDb1, $db0->get($cacheKey)); // This value should not exist if we are actually on db 0
125+
} finally {
126+
ini_set('redis.pconnect.connection_limit', $prevPoolSize);
127+
}
128+
}
76129
}

src/Symfony/Component/Cache/Traits/RedisTrait.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,10 @@ public static function createConnection(#[\SensitiveParameter] string $dsn, arra
293293
}
294294

295295
if ((null !== $auth && !$redis->auth($auth))
296-
|| ($params['dbindex'] && !$redis->select($params['dbindex']))
296+
// Due to a bug in phpredis we must always select the dbindex if persistent pooling is enabled
297+
// @see https://github.com/phpredis/phpredis/issues/1920
298+
// @see https://github.com/symfony/symfony/issues/51578
299+
|| (($params['dbindex'] || ('pconnect' === $connect && '0' !== \ini_get('redis.pconnect.pooling_enabled'))) && !$redis->select($params['dbindex']))
297300
) {
298301
$e = preg_replace('/^ERR /', '', $redis->getLastError());
299302
throw new InvalidArgumentException('Redis connection failed: '.$e.'.');

src/Symfony/Component/HttpClient/CurlHttpClient.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,8 @@ public function request(string $method, string $url, array $options = []): Respo
250250

251251
if (isset($options['normalized_headers']['content-length'][0])) {
252252
$curlopts[\CURLOPT_INFILESIZE] = (int) substr($options['normalized_headers']['content-length'][0], \strlen('Content-Length: '));
253-
}
254-
if (!isset($options['normalized_headers']['transfer-encoding'])) {
255-
$curlopts[\CURLOPT_HTTPHEADER][] = 'Transfer-Encoding:'.(isset($curlopts[\CURLOPT_INFILESIZE]) ? '' : ' chunked');
253+
} elseif (!isset($options['normalized_headers']['transfer-encoding'])) {
254+
$curlopts[\CURLOPT_INFILESIZE] = -1;
256255
}
257256

258257
if ('POST' !== $method) {

src/Symfony/Component/HttpFoundation/RedirectResponse.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public function setTargetUrl(string $url): static
8585
</html>', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8')));
8686

8787
$this->headers->set('Location', $url);
88+
$this->headers->set('Content-Type', 'text/html; charset=utf-8');
8889

8990
return $this;
9091
}

src/Symfony/Component/HttpFoundation/Tests/RedirectResponseTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ public function testGenerateLocationHeader()
4444
$this->assertEquals('foo.bar', $response->headers->get('Location'));
4545
}
4646

47+
public function testGenerateContentTypeHeader()
48+
{
49+
$response = new RedirectResponse('foo.bar');
50+
51+
$this->assertSame('text/html; charset=utf-8', $response->headers->get('Content-Type'));
52+
}
53+
4754
public function testGetTargetUrl()
4855
{
4956
$response = new RedirectResponse('foo.bar');

src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,21 @@ protected function getCasters(): array
6060
$casters = [
6161
'*' => function ($v, array $a, Stub $s, $isNested) {
6262
if (!$v instanceof Stub) {
63+
$b = $a;
6364
foreach ($a as $k => $v) {
64-
if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) {
65-
$a[$k] = new CutStub($v);
65+
if (!\is_object($v) || $v instanceof \DateTimeInterface || $v instanceof Stub) {
66+
continue;
67+
}
68+
69+
try {
70+
$a[$k] = $s = new CutStub($v);
71+
72+
if ($b[$k] === $s) {
73+
// we've hit a non-typed reference
74+
$a[$k] = $v;
75+
}
76+
} catch (\TypeError $e) {
77+
// we've hit a typed reference
6678
}
6779
}
6880
}

0 commit comments

Comments
 (0)