Skip to content

Commit 772dfbe

Browse files
committed
Merge branch '6.4' into 7.3
* 6.4: Fix Warning: curl_multi_select(): timeout must be positive [PropertyInfo] Fix ReflectionExtractor handling of underscore-only property names ObjectNormalizer: allow null and scalar [Security] Fix `HttpUtils::createRequest()` when the context’s base URL isn’t empty [Serializer] fix Inherited properties normalization [OptionsResolver] Fix missing prototype key in nested error paths Bump Symfony version to 6.4.30 Update VERSION for 6.4.29 Update CHANGELOG for 6.4.29 [Yaml] Fix parsing of unquoted multiline scalars with comments or blank lines [Clock] Align MockClock::sleep() behavior with NativeClock for negative values [OptionsResolver] Ensure remove() also unsets deprecation status Remove review state for Belarusian translations (entries 141 and 142) [ExpressionLanguage] Compile numbers with var_export in Compiler::repr for thread-safety compatibility with ext-redis 6.3 [Serializer] Fix BackedEnumNormalizer behavior with partial denormalization
2 parents 0ff2f5c + eeaa8ca commit 772dfbe

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

OptionsResolver.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,7 @@ public function remove(string|array $optionNames): static
834834

835835
foreach ((array) $optionNames as $option) {
836836
unset($this->defined[$option], $this->defaults[$option], $this->required[$option], $this->resolved[$option]);
837-
unset($this->lazy[$option], $this->normalizers[$option], $this->allowedTypes[$option], $this->allowedValues[$option], $this->info[$option]);
837+
unset($this->lazy[$option], $this->normalizers[$option], $this->allowedTypes[$option], $this->allowedValues[$option], $this->info[$option], $this->deprecated[$option]);
838838
}
839839

840840
return $this;
@@ -1011,6 +1011,11 @@ public function offsetGet(mixed $option, bool $triggerDeprecation = true): mixed
10111011
$resolver = new self();
10121012
$resolver->prototype = false;
10131013
$resolver->parentsOptions = $this->parentsOptions;
1014+
1015+
if ($this->prototype && null !== $this->prototypeIndex && null !== ($parentOptionKey = array_key_last($resolver->parentsOptions))) {
1016+
$resolver->parentsOptions[$parentOptionKey] .= \sprintf('[%s]', $this->prototypeIndex);
1017+
}
1018+
10141019
$resolver->parentsOptions[] = $option;
10151020
foreach ($this->nested[$option] as $closure) {
10161021
$closure($resolver, $this);

Tests/OptionsResolverTest.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3322,4 +3322,78 @@ public function testAccessToParentOptionFromNestedNormalizerAndLazyOption()
33223322

33233323
$this->assertSame($expectedOptions, $actualOptions);
33243324
}
3325+
3326+
public function testRemoveAlsoRemovesDeprecation()
3327+
{
3328+
$this->resolver->setDefined('foo');
3329+
$this->resolver->setDeprecated('foo', 'vendor/package', '1.0');
3330+
$this->assertTrue($this->resolver->isDeprecated('foo'));
3331+
3332+
$this->resolver->remove('foo');
3333+
$this->assertFalse($this->resolver->isDeprecated('foo'));
3334+
3335+
$this->resolver->setDefault('foo', 'bar');
3336+
$this->assertFalse($this->resolver->isDeprecated('foo'));
3337+
3338+
$count = 0;
3339+
set_error_handler(static function (int $type) use (&$count) {
3340+
if (\E_USER_DEPRECATED === $type) {
3341+
++$count;
3342+
}
3343+
3344+
return false;
3345+
});
3346+
3347+
try {
3348+
$this->resolver->resolve(['foo' => 'value']);
3349+
$this->assertSame(0, $count);
3350+
} finally {
3351+
restore_error_handler();
3352+
}
3353+
}
3354+
3355+
/**
3356+
* @group legacy
3357+
*/
3358+
public function testNestedPrototypeErrorPathHasFullContext()
3359+
{
3360+
$resolver = new OptionsResolver();
3361+
3362+
$resolver->setDefault('connections', static function (OptionsResolver $connResolver) {
3363+
$connResolver->setPrototype(true);
3364+
$connResolver->setRequired(['host', 'database']);
3365+
$connResolver->setDefault('user', 'root');
3366+
3367+
$connResolver->setDefault('replicas', static function (OptionsResolver $replicaResolver) {
3368+
$replicaResolver->setPrototype(true);
3369+
$replicaResolver->setRequired(['host']);
3370+
$replicaResolver->setDefault('user', 'read_only');
3371+
});
3372+
});
3373+
3374+
$this->expectException(MissingOptionsException::class);
3375+
$this->expectExceptionMessage('The required option "connections[main_db][replicas][1][host]" is missing.');
3376+
3377+
$options = [
3378+
'connections' => [
3379+
'main_db' => [
3380+
'host' => 'localhost',
3381+
'database' => 'app_db',
3382+
'replicas' => [
3383+
['host' => 'replica-01.local', 'user' => 'read_only'],
3384+
['user' => 'other_user'], // Index 1 -> "host" is missing here
3385+
],
3386+
],
3387+
'audit_db' => [
3388+
'host' => 'audit.local',
3389+
'database' => 'audit_db',
3390+
'replicas' => [
3391+
['host' => 'audit-replica.local'],
3392+
],
3393+
],
3394+
],
3395+
];
3396+
3397+
$resolver->resolve($options);
3398+
}
33253399
}

0 commit comments

Comments
 (0)