Skip to content

Commit e37a378

Browse files
Merge branch '7.0' into 7.1
* 7.0: [Serializer] Remove TranslatableNormalizer service when the Translator is disabled Fix support to denormalize plain object types [Routing] Restore aliases removal in RouteCollection::remove() [Workflow] Add `getEnabledTransition()` to TraceableWorkflow [DependencyInjection] Fix parsing named autowiring aliases that contain underscores Update sponsors of Symfony 7.0: Shopware, Sulu and Les-Tilleuls + Sensiolabs for Messenger & SymfonyCasts for Security components [Console] Add Les-Tilleuls.coop as sponsor of version 6.4/7.0 remove duplicated service definition
2 parents 4e2022f + a1c8134 commit e37a378

File tree

26 files changed

+280
-46
lines changed

26 files changed

+280
-46
lines changed

README.md

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,26 @@ Installation
1717
Sponsor
1818
-------
1919

20-
Symfony 6.4 is [backed][27] by
21-
- [SensioLabs][28]
22-
- [packagist.com][29]
20+
Symfony 7.0 is [backed][27] by
21+
- [Shopware][28]
22+
- [Sulu][29]
23+
- [Les-Tilleuls.coop][30]
2324

24-
As the creator of Symfony, **SensioLabs** supports companies using Symfony,
25-
with an offering encompassing consultancy, expertise, services, training, and
26-
technical assistance to ensure the success of web application development projects.
25+
**Shopware** is an open headless commerce platform powered by Symfony and Vue.js
26+
that is used by thousands of shops and supported by a huge, worldwide community
27+
of developers, agencies and merchants.
2728

28-
Private **Packagist.com** is a fast, reliable, and secure Composer repository for
29-
your private packages. It mirrors all your open-source dependencies for better
30-
availability and monitors them for security vulnerabilities.
29+
**Sulu** is the CMS for Symfony developers. It provides pre-built content-management
30+
features while giving developers the freedom to build, deploy, and maintain custom
31+
solutions using full-stack Symfony. Sulu is ideal for creating complex websites,
32+
integrating external tools, and building custom-built solutions.
3133

32-
Help Symfony by [sponsoring][30] its development!
34+
**Les-Tilleuls.coop** is a team of 70+ Symfony experts who can help you design,
35+
develop and fix your projects. We provide a wide range of professional services
36+
including development, consulting, coaching, training and audits. We also are
37+
highly skilled in JS, Go and DevOps. We are a worker cooperative!
38+
39+
Help Symfony by [sponsoring][31] its development!
3340

3441
Documentation
3542
-------------
@@ -92,6 +99,7 @@ and supported by [Symfony contributors][19].
9299
[25]: https://symfony.com/doc/current/contributing/code_of_conduct/care_team.html
93100
[26]: https://symfony.com/book
94101
[27]: https://symfony.com/backers
95-
[28]: https://sensiolabs.com
96-
[29]: https://packagist.com
97-
[30]: https://symfony.com/sponsor
102+
[28]: https://www.shopware.com
103+
[29]: https://sulu.io
104+
[30]: https://les-tilleuls.coop/
105+
[31]: https://symfony.com/sponsor

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1857,7 +1857,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
18571857
$container->removeDefinition('serializer.mapping.cache_class_metadata_factory');
18581858
}
18591859

1860-
if (!class_exists(Translator::class)) {
1860+
if (!$this->readConfigEnabled('translator', $container, $config)) {
18611861
$container->removeDefinition('serializer.normalizer.translatable');
18621862
}
18631863

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', [
4+
'annotations' => false,
5+
'http_method_override' => false,
6+
'handle_all_throwables' => true,
7+
'php_errors' => ['log' => true],
8+
'serializer' => [
9+
'enabled' => true,
10+
],
11+
'translator' => [
12+
'enabled' => false,
13+
],
14+
]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns:framework="http://symfony.com/schema/dic/symfony"
6+
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
7+
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
8+
9+
<framework:config secret="s3cr3t" http-method-override="false" handle-all-throwables="true">
10+
<framework:annotations enabled="false" />
11+
<framework:php-errors log="true" />
12+
<framework:serializer enabled="true" />
13+
<framework:translator enabled="false" />
14+
</framework:config>
15+
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
framework:
2+
annotations: false
3+
http_method_override: false
4+
handle_all_throwables: true
5+
php_errors:
6+
log: true
7+
serializer:
8+
enabled: true
9+
translator:
10+
enabled: false

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,12 @@ public function testSerializerEnabled()
14341434
$this->assertEquals($container->getDefinition('serializer.normalizer.object')->getArgument(6)['max_depth_handler'], new Reference('my.max.depth.handler'));
14351435
}
14361436

1437+
public function testSerializerWithoutTranslator()
1438+
{
1439+
$container = $this->createContainerFromFile('serializer_without_translator');
1440+
$this->assertFalse($container->hasDefinition('serializer.normalizer.translatable'));
1441+
}
1442+
14371443
public function testRegisterSerializerExtractor()
14381444
{
14391445
$container = $this->createContainerFromFile('full');

src/Symfony/Component/Console/README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@ interfaces.
77
Sponsor
88
-------
99

10-
Help Symfony by [sponsoring][1] its development!
10+
The Console component for Symfony 7.0 is [backed][1] by [Les-Tilleuls.coop][2].
11+
12+
Les-Tilleuls.coop is a team of 70+ Symfony experts who can help you design, develop and
13+
fix your projects. They provide a wide range of professional services including development,
14+
consulting, coaching, training and audits. They also are highly skilled in JS, Go and DevOps.
15+
They are a worker cooperative!
16+
17+
Help Symfony by [sponsoring][3] its development!
1118

1219
Resources
1320
---------
@@ -24,4 +31,6 @@ Credits
2431
`Resources/bin/hiddeninput.exe` is a third party binary provided within this
2532
component. Find sources and license at https://github.com/Seldaek/hidden-input.
2633

27-
[1]: https://symfony.com/sponsor
34+
[1]: https://symfony.com/backers
35+
[2]: https://les-tilleuls.coop
36+
[3]: https://symfony.com/sponsor

src/Symfony/Component/DependencyInjection/Attribute/Target.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ public function getParsedName(): string
3636
return lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $this->name))));
3737
}
3838

39-
public static function parseName(\ReflectionParameter $parameter, self &$attribute = null): string
39+
public static function parseName(\ReflectionParameter $parameter, self &$attribute = null, string &$parsedName = null): string
4040
{
4141
$attribute = null;
4242
if (!$target = $parameter->getAttributes(self::class)[0] ?? null) {
43+
$parsedName = (new self($parameter->name))->getParsedName();
44+
4345
return $parameter->name;
4446
}
4547

@@ -57,6 +59,6 @@ public static function parseName(\ReflectionParameter $parameter, self &$attribu
5759
throw new InvalidArgumentException(sprintf('Invalid #[Target] name "%s" on parameter "$%s" of "%s()": the first character must be a letter.', $name, $parameter->name, $function));
5860
}
5961

60-
return $parsedName;
62+
return preg_match('/^[a-zA-Z0-9_\x7f-\xff]++$/', $name) ? $name : $parsedName;
6163
}
6264
}

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

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -444,20 +444,30 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy
444444
$name = $target = (array_filter($reference->getAttributes(), static fn ($a) => $a instanceof Target)[0] ?? null)?->name;
445445

446446
if (null !== $name ??= $reference->getName()) {
447+
if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) {
448+
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
449+
}
450+
451+
if (null !== ($alias = $this->getCombinedAlias($type, $name)) && !$this->container->findDefinition($alias)->isAbstract()) {
452+
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
453+
}
454+
447455
$parsedName = (new Target($name))->getParsedName();
448456

449457
if ($this->container->has($alias = $type.' $'.$parsedName) && !$this->container->findDefinition($alias)->isAbstract()) {
450458
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
451459
}
452460

453-
if (null !== ($alias = $this->getCombinedAlias($type, $parsedName) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
461+
if (null !== ($alias = $this->getCombinedAlias($type, $parsedName)) && !$this->container->findDefinition($alias)->isAbstract()) {
454462
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
455463
}
456464

457-
if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) {
465+
if (($this->container->has($n = $name) && !$this->container->findDefinition($n)->isAbstract())
466+
|| ($this->container->has($n = $parsedName) && !$this->container->findDefinition($n)->isAbstract())
467+
) {
458468
foreach ($this->container->getAliases() as $id => $alias) {
459-
if ($name === (string) $alias && str_starts_with($id, $type.' $')) {
460-
return new TypedReference($name, $type, $reference->getInvalidBehavior());
469+
if ($n === (string) $alias && str_starts_with($id, $type.' $')) {
470+
return new TypedReference($n, $type, $reference->getInvalidBehavior());
461471
}
462472
}
463473
}
@@ -471,7 +481,7 @@ private function getAutowiredReference(TypedReference $reference, bool $filterTy
471481
return new TypedReference($type, $type, $reference->getInvalidBehavior());
472482
}
473483

474-
if (null !== ($alias = $this->getCombinedAlias($type) ?? null) && !$this->container->findDefinition($alias)->isAbstract()) {
484+
if (null !== ($alias = $this->getCombinedAlias($type)) && !$this->container->findDefinition($alias)->isAbstract()) {
475485
return new TypedReference($alias, $type, $reference->getInvalidBehavior());
476486
}
477487

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,16 +187,19 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
187187

188188
$typeHint = ltrim(ProxyHelper::exportType($parameter) ?? '', '?');
189189

190-
$name = Target::parseName($parameter);
190+
$name = Target::parseName($parameter, parsedName: $parsedName);
191191

192-
if ($typeHint && \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$name, $bindings)) {
192+
if ($typeHint && (
193+
\array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$name, $bindings)
194+
|| \array_key_exists($k = preg_replace('/(^|[(|&])\\\\/', '\1', $typeHint).' $'.$parsedName, $bindings)
195+
)) {
193196
$arguments[$key] = $this->getBindingValue($bindings[$k]);
194197

195198
continue;
196199
}
197200

198-
if (\array_key_exists('$'.$name, $bindings)) {
199-
$arguments[$key] = $this->getBindingValue($bindings['$'.$name]);
201+
if (\array_key_exists($k = '$'.$name, $bindings) || \array_key_exists($k = '$'.$parsedName, $bindings)) {
202+
$arguments[$key] = $this->getBindingValue($bindings[$k]);
200203

201204
continue;
202205
}
@@ -207,7 +210,7 @@ protected function processValue(mixed $value, bool $isRoot = false): mixed
207210
continue;
208211
}
209212

210-
if (isset($bindingNames[$name]) || isset($bindingNames[$parameter->name])) {
213+
if (isset($bindingNames[$name]) || isset($bindingNames[$parsedName]) || isset($bindingNames[$parameter->name])) {
211214
$bindingKey = array_search($binding, $bindings, true);
212215
$argumentType = substr($bindingKey, 0, strpos($bindingKey, ' '));
213216
$this->errorMessages[] = sprintf('Did you forget to add the type "%s" to argument "$%s" of method "%s::%s()"?', $argumentType, $parameter->name, $reflectionMethod->class, $reflectionMethod->name);

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,18 @@ public function testAutowireWithNamedArgs()
11911191
$this->assertEquals([new TypedReference(A::class, A::class), 'abc'], $container->getDefinition('foo')->getArguments());
11921192
}
11931193

1194+
public function testAutowireUnderscoreNamedArgument()
1195+
{
1196+
$container = new ContainerBuilder();
1197+
1198+
$container->autowire(\DateTimeImmutable::class.' $now_datetime', \DateTimeImmutable::class);
1199+
$container->autowire('foo', UnderscoreNamedArgument::class)->setPublic(true);
1200+
1201+
(new AutowirePass())->process($container);
1202+
1203+
$this->assertInstanceOf(\DateTimeImmutable::class, $container->get('foo')->now_datetime);
1204+
}
1205+
11941206
public function testAutowireDefaultValueParametersLike()
11951207
{
11961208
$container = new ContainerBuilder();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ public static function getSubscribedServices(): array
403403

404404
$expected = [
405405
'some.service' => new ServiceClosureArgument(new TypedReference('stdClass $someService', 'stdClass')),
406-
'some_service' => new ServiceClosureArgument(new TypedReference('stdClass $someService', 'stdClass')),
406+
'some_service' => new ServiceClosureArgument(new TypedReference('stdClass $some_service', 'stdClass')),
407407
'another_service' => new ServiceClosureArgument(new TypedReference('stdClass $anotherService', 'stdClass')),
408408
];
409409
$this->assertEquals($expected, $container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,14 @@ public function __construct(A $a, Lille $lille, $foo = 'some_val')
213213
}
214214
}
215215

216+
class UnderscoreNamedArgument
217+
{
218+
public function __construct(
219+
public \DateTimeImmutable $now_datetime,
220+
) {
221+
}
222+
}
223+
216224
/*
217225
* Classes used for testing createResourceForClass
218226
*/

src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services14.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
55
<services>
6-
<service id="monolog.logger" parent="monolog.logger_prototype">
7-
<argument index="0">app</argument>
8-
</service>
9-
106
<service id="logger" alias="monolog.logger" />
117

128
<service id="monolog.logger" parent="monolog.logger_prototype">

src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ public function process(ContainerBuilder $container): void
125125
$type = preg_replace('/(^|[(|&])\\\\/', '\1', $target = ltrim(ProxyHelper::exportType($p) ?? '', '?'));
126126
$invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
127127
$autowireAttributes = $autowire ? $emptyAutowireAttributes : [];
128+
$parsedName = $p->name;
129+
$k = null;
128130

129131
if (isset($arguments[$r->name][$p->name])) {
130132
$target = $arguments[$r->name][$p->name];
@@ -135,7 +137,11 @@ public function process(ContainerBuilder $container): void
135137
} elseif ($p->allowsNull() && !$p->isOptional()) {
136138
$invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE;
137139
}
138-
} elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p)]) || isset($bindings[$bindingName = '$'.$name]) || isset($bindings[$bindingName = $type])) {
140+
} elseif (isset($bindings[$bindingName = $type.' $'.$name = Target::parseName($p, $k, $parsedName)])
141+
|| isset($bindings[$bindingName = $type.' $'.$parsedName])
142+
|| isset($bindings[$bindingName = '$'.$name])
143+
|| isset($bindings[$bindingName = $type])
144+
) {
139145
$binding = $bindings[$bindingName];
140146

141147
[$bindingValue, $bindingId, , $bindingType, $bindingFile] = $binding->getValues();

src/Symfony/Component/Messenger/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ other applications or via message queues.
77
Sponsor
88
-------
99

10-
The Messenger component for Symfony 6.4 is [backed][1] by [SensioLabs][2].
10+
The Messenger component for Symfony 7.0 is [backed][1] by [SensioLabs][2].
1111

1212
As the creator of Symfony, SensioLabs supports companies using Symfony, with an
1313
offering encompassing consultancy, expertise, services, training, and technical

src/Symfony/Component/Routing/RouteCollection.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,21 @@ public function get(string $name): ?Route
142142
*/
143143
public function remove(string|array $name): void
144144
{
145-
$names = (array) $name;
146-
foreach ($names as $n) {
147-
unset($this->routes[$n], $this->priorities[$n]);
145+
$routes = [];
146+
foreach ((array) $name as $n) {
147+
if (isset($this->routes[$n])) {
148+
$routes[] = $n;
149+
}
150+
151+
unset($this->routes[$n], $this->priorities[$n], $this->aliases[$n]);
152+
}
153+
154+
if (!$routes) {
155+
return;
148156
}
149157

150158
foreach ($this->aliases as $k => $alias) {
151-
if (\in_array($alias->getId(), $names, true)) {
159+
if (\in_array($alias->getId(), $routes, true)) {
152160
unset($this->aliases[$k]);
153161
}
154162
}

src/Symfony/Component/Routing/Tests/RouteCollectionTest.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,19 +219,22 @@ public function testGet()
219219
public function testRemove()
220220
{
221221
$collection = new RouteCollection();
222-
$collection->add('foo', $foo = new Route('/foo'));
222+
$collection->add('foo', new Route('/foo'));
223223

224224
$collection1 = new RouteCollection();
225225
$collection1->add('bar', $bar = new Route('/bar'));
226226
$collection->addCollection($collection1);
227227
$collection->add('last', $last = new Route('/last'));
228-
$collection->addAlias('ccc_my_custom_alias', 'foo');
228+
$collection->addAlias('alias_removed_when_removing_route_foo', 'foo');
229+
$collection->addAlias('alias_directly_removed', 'bar');
229230

230231
$collection->remove('foo');
231232
$this->assertSame(['bar' => $bar, 'last' => $last], $collection->all(), '->remove() can remove a single route');
233+
$collection->remove('alias_directly_removed');
234+
$this->assertNull($collection->getAlias('alias_directly_removed'));
232235
$collection->remove(['bar', 'last']);
233236
$this->assertSame([], $collection->all(), '->remove() accepts an array and can remove multiple routes at once');
234-
$this->assertNull($collection->getAlias('ccc_my_custom_alias'));
237+
$this->assertNull($collection->getAlias('alias_removed_when_removing_route_foo'));
235238
}
236239

237240
public function testSetHost()

src/Symfony/Component/Security/Core/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ if (!$accessDecisionManager->decide($token, ['ROLE_ADMIN'])) {
4141
Sponsor
4242
-------
4343

44-
The Security component for Symfony 6.4 is [backed][1] by [SymfonyCasts][2].
44+
The Security component for Symfony 7.0 is [backed][1] by [SymfonyCasts][2].
4545

4646
Learn Symfony faster by watching real projects being built and actively coding
4747
along with them. SymfonyCasts bridges that learning gap, bringing you video

src/Symfony/Component/Security/Csrf/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The Security CSRF (cross-site request forgery) component provides a class
77
Sponsor
88
-------
99

10-
The Security component for Symfony 6.4 is [backed][1] by [SymfonyCasts][2].
10+
The Security component for Symfony 7.0 is [backed][1] by [SymfonyCasts][2].
1111

1212
Learn Symfony faster by watching real projects being built and actively coding
1313
along with them. SymfonyCasts bridges that learning gap, bringing you video

src/Symfony/Component/Security/Http/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ $ composer require symfony/security-http
1515
Sponsor
1616
-------
1717

18-
The Security component for Symfony 6.4 is [backed][1] by [SymfonyCasts][2].
18+
The Security component for Symfony 7.0 is [backed][1] by [SymfonyCasts][2].
1919

2020
Learn Symfony faster by watching real projects being built and actively coding
2121
along with them. SymfonyCasts bridges that learning gap, bringing you video

0 commit comments

Comments
 (0)