Skip to content

Commit b38026d

Browse files
committed
Merge branch '7.3' into 7.4
* 7.3: 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 7.3.8 Update VERSION for 7.3.7 Update CHANGELOG for 7.3.7 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 [HttpFoundation] Fix parsing pathinfo with no leading slash
2 parents 3324bca + 772dfbe commit b38026d

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-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: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3424,4 +3424,77 @@ public function testAccessToParentOptionFromNestedNormalizerAndLazyOption()
34243424

34253425
$this->assertSame($expectedOptions, $actualOptions);
34263426
}
3427+
3428+
public function testRemoveAlsoRemovesDeprecation()
3429+
{
3430+
$this->resolver->setDefined('foo');
3431+
$this->resolver->setDeprecated('foo', 'vendor/package', '1.0');
3432+
$this->assertTrue($this->resolver->isDeprecated('foo'));
3433+
3434+
$this->resolver->remove('foo');
3435+
$this->assertFalse($this->resolver->isDeprecated('foo'));
3436+
3437+
$this->resolver->setDefault('foo', 'bar');
3438+
$this->assertFalse($this->resolver->isDeprecated('foo'));
3439+
3440+
$count = 0;
3441+
set_error_handler(static function (int $type) use (&$count) {
3442+
if (\E_USER_DEPRECATED === $type) {
3443+
++$count;
3444+
}
3445+
3446+
return false;
3447+
});
3448+
3449+
try {
3450+
$this->resolver->resolve(['foo' => 'value']);
3451+
$this->assertSame(0, $count);
3452+
} finally {
3453+
restore_error_handler();
3454+
}
3455+
}
3456+
3457+
#[IgnoreDeprecations]
3458+
#[Group('legacy')]
3459+
public function testNestedPrototypeErrorPathHasFullContext()
3460+
{
3461+
$resolver = new OptionsResolver();
3462+
3463+
$resolver->setDefault('connections', static function (OptionsResolver $connResolver) {
3464+
$connResolver->setPrototype(true);
3465+
$connResolver->setRequired(['host', 'database']);
3466+
$connResolver->setDefault('user', 'root');
3467+
3468+
$connResolver->setDefault('replicas', static function (OptionsResolver $replicaResolver) {
3469+
$replicaResolver->setPrototype(true);
3470+
$replicaResolver->setRequired(['host']);
3471+
$replicaResolver->setDefault('user', 'read_only');
3472+
});
3473+
});
3474+
3475+
$this->expectException(MissingOptionsException::class);
3476+
$this->expectExceptionMessage('The required option "connections[main_db][replicas][1][host]" is missing.');
3477+
3478+
$options = [
3479+
'connections' => [
3480+
'main_db' => [
3481+
'host' => 'localhost',
3482+
'database' => 'app_db',
3483+
'replicas' => [
3484+
['host' => 'replica-01.local', 'user' => 'read_only'],
3485+
['user' => 'other_user'], // Index 1 -> "host" is missing here
3486+
],
3487+
],
3488+
'audit_db' => [
3489+
'host' => 'audit.local',
3490+
'database' => 'audit_db',
3491+
'replicas' => [
3492+
['host' => 'audit-replica.local'],
3493+
],
3494+
],
3495+
],
3496+
];
3497+
3498+
$resolver->resolve($options);
3499+
}
34273500
}

0 commit comments

Comments
 (0)