Skip to content

Commit 8ffdef2

Browse files
Merge branch '5.0'
* 5.0: [DI] Service locators can't be decorated [HttpClient] force HTTP/1.1 when NTLM auth is used [Validation][FrameworkBundle] Allow EnableAutoMapping to work without auto-mapping namespaces [Console][SymfonyQuestionHelper] Handle multibytes question choices keys and custom prompt [DI] fix auto-binding service providers to their service subscribers [Mailer] fixed undefined index when sending mail
2 parents 45d65cc + 3c348df commit 8ffdef2

File tree

20 files changed

+204
-58
lines changed

20 files changed

+204
-58
lines changed

UPGRADE-4.4.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ Lock
164164
* Deprecated `Symfony\Component\Lock\StoreInterface` in favor of `Symfony\Component\Lock\BlockingStoreInterface` and
165165
`Symfony\Component\Lock\PersistingStoreInterface`.
166166
* `Factory` is deprecated, use `LockFactory` instead
167-
* Deprecated services `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract`,
168-
use `StoreFactory::createStore` instead.
167+
* Deprecated services `lock.store.flock`, `lock.store.semaphore`, `lock.store.memcached.abstract` and `lock.store.redis.abstract`,
168+
use `StoreFactory::createStore` instead.
169169

170170
Mailer
171171
------
@@ -360,6 +360,7 @@ TwigBundle
360360
Validator
361361
---------
362362

363+
* [BC BREAK] Using null as `$classValidatorRegexp` value in `DoctrineLoader::__construct` or `PropertyInfoLoader::__construct` will not enable auto-mapping for all classes anymore, use `'{.*}'` instead.
363364
* Deprecated passing an `ExpressionLanguage` instance as the second argument of `ExpressionValidator::__construct()`.
364365
* Deprecated using anything else than a `string` as the code of a `ConstraintViolation`, a `string` type-hint will
365366
be added to the constructor of the `ConstraintViolation` class and to the `ConstraintViolationBuilder::setCode()`

src/Symfony/Bridge/Doctrine/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ CHANGELOG
1212
4.4.0
1313
-----
1414

15+
* [BC BREAK] using null as `$classValidatorRegexp` value in `DoctrineLoader::__construct` will not enable auto-mapping for all classes anymore, use `'{.*}'` instead.
1516
* added `DoctrineClearEntityManagerWorkerSubscriber`
1617
* deprecated `RegistryInterface`, use `Doctrine\Persistence\ManagerRegistry`
1718
* added support for invokable event listeners

src/Symfony/Bridge/Doctrine/Tests/Validator/DoctrineLoaderTest.php

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
use Symfony\Component\Validator\Mapping\TraversalStrategy;
3131
use Symfony\Component\Validator\Tests\Fixtures\Entity;
3232
use Symfony\Component\Validator\Validation;
33-
use Symfony\Component\Validator\ValidatorBuilder;
3433

3534
/**
3635
* @author Kévin Dunglas <dunglas@gmail.com>
@@ -151,10 +150,6 @@ public function testLoadClassMetadata()
151150

152151
public function testFieldMappingsConfiguration()
153152
{
154-
if (!method_exists(ValidatorBuilder::class, 'addLoader')) {
155-
$this->markTestSkipped('Auto-mapping requires symfony/validation 4.2+');
156-
}
157-
158153
$validator = Validation::createValidatorBuilder()
159154
->enableAnnotationMapping()
160155
->addXmlMappings([__DIR__.'/../Resources/validator/BaseUser.xml'])
@@ -178,7 +173,7 @@ public function testFieldMappingsConfiguration()
178173
*/
179174
public function testClassValidator(bool $expected, string $classValidatorRegexp = null)
180175
{
181-
$doctrineLoader = new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), $classValidatorRegexp);
176+
$doctrineLoader = new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), $classValidatorRegexp, false);
182177

183178
$classMetadata = new ClassMetadata(DoctrineLoaderEntity::class);
184179
$this->assertSame($expected, $doctrineLoader->loadClassMetadata($classMetadata));
@@ -187,21 +182,18 @@ public function testClassValidator(bool $expected, string $classValidatorRegexp
187182
public function regexpProvider()
188183
{
189184
return [
190-
[true, null],
185+
[false, null],
186+
[true, '{.*}'],
191187
[true, '{^'.preg_quote(DoctrineLoaderEntity::class).'$|^'.preg_quote(Entity::class).'$}'],
192188
[false, '{^'.preg_quote(Entity::class).'$}'],
193189
];
194190
}
195191

196192
public function testClassNoAutoMapping()
197193
{
198-
if (!method_exists(ValidatorBuilder::class, 'addLoader')) {
199-
$this->markTestSkipped('Auto-mapping requires symfony/validation 4.2+');
200-
}
201-
202194
$validator = Validation::createValidatorBuilder()
203195
->enableAnnotationMapping()
204-
->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager()))
196+
->addLoader(new DoctrineLoader(DoctrineTestHelper::createTestEntityManager(), '{.*}'))
205197
->getValidator();
206198

207199
$classMetadata = $validator->getMetadataFor(new DoctrineLoaderNoAutoMappingEntity());

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode)
724724
->end()
725725
->end()
726726
->arrayNode('auto_mapping')
727-
->info('A collection of namespaces for which auto-mapping will be enabled.')
727+
->info('A collection of namespaces for which auto-mapping will be enabled by default, or null to opt-in with the EnableAutoMapping constraint.')
728728
->example([
729729
'App\\Entity\\' => [],
730730
'App\\WithSpecificLoaders\\' => ['validator.property_info_loader'],

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ private function registerValidationConfiguration(array $config, ContainerBuilder
11871187
}
11881188

11891189
$container->setParameter('validator.auto_mapping', $config['auto_mapping']);
1190-
if (!$propertyInfoEnabled || !$config['auto_mapping'] || !class_exists(PropertyInfoLoader::class)) {
1190+
if (!$propertyInfoEnabled || !class_exists(PropertyInfoLoader::class)) {
11911191
$container->removeDefinition('validator.property_info_loader');
11921192
}
11931193

src/Symfony/Component/Console/Helper/QuestionHelper.php

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -166,22 +166,36 @@ protected function writePrompt(OutputInterface $output, Question $question)
166166
$message = $question->getQuestion();
167167

168168
if ($question instanceof ChoiceQuestion) {
169-
$maxWidth = max(array_map([$this, 'strlen'], array_keys($question->getChoices())));
170-
171-
$messages = (array) $question->getQuestion();
172-
foreach ($question->getChoices() as $key => $value) {
173-
$width = $maxWidth - $this->strlen($key);
174-
$messages[] = ' [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
175-
}
176-
177-
$output->writeln($messages);
169+
$output->writeln(array_merge([
170+
$question->getQuestion(),
171+
], $this->formatChoiceQuestionChoices($question, 'info')));
178172

179173
$message = $question->getPrompt();
180174
}
181175

182176
$output->write($message);
183177
}
184178

179+
/**
180+
* @param string $tag
181+
*
182+
* @return string[]
183+
*/
184+
protected function formatChoiceQuestionChoices(ChoiceQuestion $question, $tag)
185+
{
186+
$messages = [];
187+
188+
$maxWidth = max(array_map('self::strlen', array_keys($choices = $question->getChoices())));
189+
190+
foreach ($choices as $key => $value) {
191+
$padding = str_repeat(' ', $maxWidth - self::strlen($key));
192+
193+
$messages[] = sprintf(" [<$tag>%s$padding</$tag>] %s", $key, $value);
194+
}
195+
196+
return $messages;
197+
}
198+
185199
/**
186200
* Outputs an error message.
187201
*/

src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ protected function writePrompt(OutputInterface $output, Question $question)
6868

6969
$output->writeln($text);
7070

71+
$prompt = ' > ';
72+
7173
if ($question instanceof ChoiceQuestion) {
72-
$width = max(array_map('strlen', array_keys($question->getChoices())));
74+
$output->writeln($this->formatChoiceQuestionChoices($question, 'comment'));
7375

74-
foreach ($question->getChoices() as $key => $value) {
75-
$output->writeln(sprintf(" [<comment>%-${width}s</comment>] %s", $key, $value));
76-
}
76+
$prompt = $question->getPrompt();
7777
}
7878

79-
$output->write(' > ');
79+
$output->write($prompt);
8080
}
8181

8282
/**

src/Symfony/Component/Console/Tests/Helper/SymfonyQuestionHelperTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,49 @@ public function testAskThrowsExceptionOnMissingInput()
130130
$dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('')), $this->createOutputInterface(), new Question('What\'s your name?'));
131131
}
132132

133+
public function testChoiceQuestionPadding()
134+
{
135+
$choiceQuestion = new ChoiceQuestion('qqq', [
136+
'foo' => 'foo',
137+
'żółw' => 'bar',
138+
'łabądź' => 'baz',
139+
]);
140+
141+
(new SymfonyQuestionHelper())->ask(
142+
$this->createStreamableInputInterfaceMock($this->getInputStream("foo\n")),
143+
$output = $this->createOutputInterface(),
144+
$choiceQuestion
145+
);
146+
147+
$this->assertOutputContains(<<<EOT
148+
qqq:
149+
[foo ] foo
150+
[żółw ] bar
151+
[łabądź] baz
152+
>
153+
EOT
154+
, $output);
155+
}
156+
157+
public function testChoiceQuestionCustomPrompt()
158+
{
159+
$choiceQuestion = new ChoiceQuestion('qqq', ['foo']);
160+
$choiceQuestion->setPrompt(' >ccc> ');
161+
162+
(new SymfonyQuestionHelper())->ask(
163+
$this->createStreamableInputInterfaceMock($this->getInputStream("foo\n")),
164+
$output = $this->createOutputInterface(),
165+
$choiceQuestion
166+
);
167+
168+
$this->assertOutputContains(<<<EOT
169+
qqq:
170+
[0] foo
171+
>ccc>
172+
EOT
173+
, $output);
174+
}
175+
133176
protected function getInputStream($input)
134177
{
135178
$stream = fopen('php://memory', 'r+', false);

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,15 @@ public function __construct()
5252
new ValidateEnvPlaceholdersPass(),
5353
new ResolveChildDefinitionsPass(),
5454
new RegisterServiceSubscribersPass(),
55-
new DecoratorServicePass(),
5655
new ResolveParameterPlaceHoldersPass(false),
57-
new ResolveFactoryClassPass(),
5856
new ResolveNamedArgumentsPass(),
59-
new AutowireRequiredMethodsPass(),
60-
new AutowireRequiredPropertiesPass(),
6157
new ResolveBindingsPass(),
6258
new ServiceLocatorTagPass(),
6359
new CheckDefinitionValidityPass(),
60+
new DecoratorServicePass(),
61+
new ResolveFactoryClassPass(),
62+
new AutowireRequiredMethodsPass(),
63+
new AutowireRequiredPropertiesPass(),
6464
new AutowirePass(false),
6565
new ResolveTaggedIteratorArgumentPass(),
6666
new ResolveServiceSubscribersPass(),

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14+
use Psr\Container\ContainerInterface as PsrContainerInterface;
15+
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
1416
use Symfony\Component\DependencyInjection\ContainerInterface;
1517
use Symfony\Component\DependencyInjection\Definition;
1618
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1719
use Symfony\Component\DependencyInjection\Reference;
1820
use Symfony\Component\DependencyInjection\TypedReference;
21+
use Symfony\Contracts\Service\ServiceProviderInterface;
1922
use Symfony\Contracts\Service\ServiceSubscriberInterface;
2023

2124
/**
@@ -105,7 +108,14 @@ protected function processValue($value, bool $isRoot = false)
105108
throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId));
106109
}
107110

108-
$value->addTag('container.service_subscriber.locator', ['id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId)]);
111+
$locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId);
112+
113+
$value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]);
114+
115+
$value->setBindings([
116+
PsrContainerInterface::class => new BoundArgument($locatorRef, false),
117+
ServiceProviderInterface::class => new BoundArgument($locatorRef, false),
118+
] + $value->getBindings());
109119

110120
return parent::processValue($value);
111121
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy