8000 Merge branch '5.4' into 6.0 · symfony/symfony@4e69ecd · GitHub
[go: up one dir, main page]

Skip to content

Commit 4e69ecd

Browse files
Merge branch '5.4' into 6.0
* 5.4: [HttpClient] fix RetryableHttpClient when a response is canceled Deprecate passing null as $requestIp to IpUtils::checkIp(), checkIp4() and checkIp6() [Uid] fix 4 missing bits of entropy in UUIDv4 Add a warning in WDT if using symfony/symfony [Notifier][Twilio] Ensure from/sender is valid via regex Lower log level in case of retry GuardEvent::getTransition() cannot return null [String] Add `trimSuffix()` and `trimPrefix()` methods [DependencyInjection] autowire union and intersection types [Runtime] Drop class validation of composer "extra.runtime.class"
2 parents a5b810b + 7a7240f commit 4e69ecd

File tree

31 files changed

+484
-64
lines changed

31 files changed

+484
-64
lines changed

UPGRADE-5.4.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ HttpKernel
3939
HttpFoundation
4040
--------------
4141

42+
* Deprecate passing `null` as `$requestIp` to `IpUtils::checkIp()`, `IpUtils::checkIp4()` or `IpUtils::checkIp6()`, pass an empty string instead.
4243
* Mark `Request::get()` internal, use explicit input sources instead
4344
* Deprecate `upload_progress.*` and `url_rewriter.tags` session options
4445

src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\WebProfilerBundle\Controller;
1313

14+
use Symfony\Bundle\FullStack;
1415
use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler;
1516
use Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager;
1617
use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -152,6 +153,7 @@ public function toolbarAction(Request $request, string $token = null): Response
152153
}
153154

154155
return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/toolbar.html.twig', [
156+
'full_stack' => class_exists(FullStack::class),
155157
'request' => $request,
156158
'profile' => $profile,
157159
'templates' => $this->getTemplateManager()->getNames($profile),

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,11 @@ div.sf-toolbar .sf-toolbar-block a:hover {
545545
margin-right: 10px;
546546
}
547547

548+
.sf-full-stack {
549+
left: 0px;
550+
font-size: 12px;
551+
}
552+
548553
/***** Media query print: Do not print the Toolbar. *****/
549554
@media print {
550555
.sf-toolbar {

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.html.twig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@
2222
{% endwith %}
2323
{% endif %}
2424
{% endfor %}
25+
{% if full_stack %}
26+
<div class="sf-full-stack sf-toolbar-block sf-toolbar-block-full-stack sf-toolbar-status-red sf-toolbar-block-right">
27+
<div class="sf-toolbar-icon">
28+
<span class="sf-toolbar-value">Using symfony/symfony is NOT supported</span>
29+
</div>
30+
<div class="sf-toolbar-info sf-toolbar-status-red">
31+
<p>This project is using Symfony via the "symfony/symfony" package.</p>
32+
<p>This is NOT supported anymore since Symfony 4.0.</p>
33+
<p>Even if it seems to work well, it has some important limitations with no workarounds.</p>
34+
<p>Using this package also makes your project slower.</p>
35+
36+
<strong>Please, stop using this package and replace it with individual packages instead.</strong>
37+
</div>
38+
<div></div>
39+
</div>
40+
{% endif %}
2541

2642
<button class="hide-button" type="button" id="sfToolbarHideButton-{{ token }}" title="Close Toolbar" accesskey="D" aria-expanded="true" aria-controls="sfToolbarMainContent-{{ token }}">
2743
{{ include('@WebProfiler/Icon/close.svg') }}

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ CHANGELOG
1616
* Add `service_closure()` to the PHP-DSL
1717
* Add support for autoconfigurable attributes on methods, properties and parameters
1818
* Make auto-aliases private by default
19+
* Add support for autowiring union and intersection types
1920

2021
5.3
2122
---

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class AutowirePass extends AbstractRecursivePass
4545
private ?int $decoratedMethodIndex = null;
4646
private ?int $decoratedMethodArgumentIndex = null;
4747
private ?self $typesClone = null;
48+
private array $combinedAliases;
4849

4950
public function __construct(bool $throwOnAutowireException = true)
5051
{
@@ -60,6 +61,8 @@ public function __construct(bool $throwOnAutowireException = true)
6061
*/
6162
public function process(ContainerBuilder $container)
6263
{
64+
$this->populateCombinedAliases($container);
65+
6366
try {
6467
$this->typesClone = clone $this;
6568
parent::process($container);
@@ -72,6 +75,7 @@ public function process(ContainerBuilder $container)
7275
$this->decoratedMethodIndex = null;
7376
$this->decoratedMethodArgumentIndex = null;
7477
$this->typesClone = null;
78+
$this->combinedAliases = [];
7579
}
7680
}
7781

@@ -358,8 +362,12 @@ private function getAutowiredReference(TypedReference $reference): ?TypedReferen
358362
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
359363
}
360364

365+
if (null !== ($alias = $this->combinedAliases[$alias] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
366+
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
367+
}
368+
361369
if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) {
362-
foreach ($this->container->getAliases() as $id => $alias) {
370+
foreach ($this->container->getAliases() + $this->combinedAliases as $id => $alias) {
363371
if ($name === (string) $alias && str_starts_with($id, $type.' $')) {
364372
return new TypedReference($name, $type, $reference->getInvalidBehavior());
365373
}
@@ -371,6 +379,10 @@ private function getAutowiredReference(TypedReference $reference): ?TypedReferen
371379
return new TypedReference($type, $type, $reference->getInvalidBehavior());
372380
}
373381

382+
if (null !== ($alias = $this->combinedAliases[$type] ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
383+
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
384+
}
385+
374386
return null;
375387
}
376388

@@ -560,4 +572,45 @@ private function populateAutowiringAlias(string $id): void
560572
$this->autowiringAliases[$type][$name] = $name;
561573
}
562574
}
575+
576+
private function populateCombinedAliases(ContainerBuilder $container): void
577+
{
578+
$this->combinedAliases = [];
579+
$reverseAliases = [];
580+
581+
foreach ($container->getAliases() as $id => $alias) {
582+
if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) {
583+
continue;
584+
}
585+
586+
$type = $m[2];
587+
$name = $m[3] ?? '';
588+
$reverseAliases[(string) $alias][$name][] = $type;
589+
}
590+
591+
foreach ($reverseAliases as $alias => $names) {
592+
foreach ($names as $name => $types) {
593+
if (2 > $count = \count($types)) {
594+
continue;
595+
}
596+
sort($types);
597+
$i = 1 << $count;
598+
599+
// compute the powerset of the list of types
600+
while ($i--) {
601+
$set = [];
602+
for ($j = 0; $j < $count; ++$j) {
603+
if ($i & (1 << $j)) {
604+
$set[] = $types[$j];
605+
}
606+
}
607+
608+
if (2 <= \count($set)) {
609+
$this->combinedAliases[implode('&', $set).('' === $name ? '' : ' $'.$name)] = $alias;
610+
$this->combinedAliases[implode('|', $set).('' === $name ? '' : ' $'.$name)] = $alias;
611+
}
612+
}
613+
}
614+
}
615+
}
563616
}

src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionPa
7070
}
7171
}
7272

73+
sort($types);
74+
7375
return $types ? implode($glue, $types) : null;
7476
}
7577
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,28 @@ public function testTypeNotGuessableUnionType()
254254
$pass->process($container);
255255
}
256256

257+
public function testGuessableUnionType()
258+
{
259+
$container = new ContainerBuilder();
260+
261+
$container->register('b', \stcClass::class);
262+
$container->setAlias(CollisionA::class.' $collision', 'b');
263+
$container->setAlias(CollisionB::class.' $collision', 'b');
264+
265+
$aDefinition = $container->register('a', UnionClasses::class);
266+
$aDefinition->setAutowired(true);
267+
268+
$pass = new AutowirePass();
269+
$pass->process($container);
270+
271+
$this->assertSame('b', (string) $aDefinition->getArgument(0));
272+
}
273+
257274
/**
258275
* @requires PHP 8.1
259276
*/
260277
public function testTypeNotGuessableIntersectionType()
261278
{
262-
$this->expectException(AutowiringFailedException::class);
263-
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\IntersectionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface&Symfony\Component\DependencyInjection\Tests\Compiler\AnotherInterface" but this class was not found.');
264279
$container = new ContainerBuilder();
265280

266281
$container->register(CollisionInterface::class);
@@ -269,8 +284,32 @@ public function testTypeNotGuessableIntersectionType()
269284
$aDefinition = $container->register('a', IntersectionClasses::class);
270285
$aDefinition->setAutowired(true);
271286

287+
$pass = new AutowirePass();
288+
289+
$this->expectException(AutowiringFailedException::class);
290+
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\IntersectionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\AnotherInterface&Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but this class was not found.');
291+
$pass->process($container);
292+
}
293+
294+
/**
295+
* @requires PHP 8.1
296+
*/
297+
public function testGuessableIntersectionType()
298+
{
299+
$container = new ContainerBuilder();
300+
301+
$container->register('b', \stcClass::class);
302+
$container->setAlias(CollisionInterface::class, 'b');
303+
$container->setAlias(AnotherInterface::class, 'b');
304+
$container->setAlias(DummyInterface::class, 'b');
305+
306+
$aDefinition = $container->register('a', IntersectionClasses::class);
307+
$aDefinition->setAutowired(true);
308+
272309
$pass = new AutowirePass();
273310
$pass->process($container);
311+
312+
$this->assertSame('b', (string) $aDefinition->getArgument(0));
274313
}
275314

276315
public function testTypeNotGuessableWithTypeSet()
@@ -503,7 +542,7 @@ public function testScalarArgsCannotBeAutowired()
503542
public function testUnionScalarArgsCannotBeAutowired()
504543
{
505544
$this->expectException(AutowiringFailedException::class);
506-
$this->expectExceptionMessage('Cannot autowire service "union_scalars": argument "$timeout" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionScalars::__construct()" is type-hinted "int|float", you should configure its value explicitly.');
545+
$this->expectExceptionMessage('Cannot autowire service "union_scalars": argument "$timeout" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionScalars::__construct()" is type-hinted "float|int", you should configure its value explicitly.');
507546
$container = new ContainerBuilder();
508547

509548
$container->register('union_scalars', UnionScalars::class)

src/Symfony/Component/HttpClient/EventSourceHttpClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public function request(string $method, string $url, array $options = []): Respo
7878
try {
7979
$isTimeout = $chunk->isTimeout();
8080

81-
if (null !== $chunk->getInformationalStatus()) {
81+
if (null !== $chunk->getInformationalStatus() || $context->getInfo('canceled')) {
8282
yield $chunk;
8383

8484
return;

src/Symfony/Component/HttpClient/NoPrivateNetworkHttpClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public function request(string $method, string $url, array $options = []): Respo
7676

7777
$options['on_progress'] = function (int $dlNow, int $dlSize, array $info) use ($onProgress, $subnets, &$lastPrimaryIp): void {
7878
if ($info['primary_ip'] !== $lastPrimaryIp) {
79-
if (IpUtils::checkIp($info['primary_ip'], $subnets ?? self::PRIVATE_SUBNETS)) {
79+
if ($info['primary_ip'] && IpUtils::checkIp($info['primary_ip'], $subnets ?? self::PRIVATE_SUBNETS)) {
8080
throw new TransportException(sprintf('IP "%s" is blocked for "%s".', $info['primary_ip'], $info['url']));
8181
}
8282

0 commit comments

Comments
 (0)
0