mirror of
https://github.com/linuxserver/Heimdall.git
synced 2025-12-09 08:23:53 +09:00
Updates to vendors etc
This commit is contained in:
9
vendor/symfony/options-resolver/CHANGELOG.md
vendored
9
vendor/symfony/options-resolver/CHANGELOG.md
vendored
@@ -1,10 +1,17 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
7.3
|
||||
---
|
||||
|
||||
* Support union type in `OptionResolver::setAllowedTypes()` method
|
||||
* Add `OptionsResolver::setOptions()` and `OptionConfigurator::options()` methods
|
||||
* Deprecate defining nested options via `setDefault()`, use `setOptions()` instead
|
||||
|
||||
6.4
|
||||
---
|
||||
|
||||
* Improve message with full path on invalid type in nested option
|
||||
* Improve message with full path on invalid type in nested option
|
||||
|
||||
6.3
|
||||
---
|
||||
|
||||
@@ -29,7 +29,7 @@ class OptionsResolverIntrospector
|
||||
$this->get = \Closure::bind(function ($property, $option, $message) {
|
||||
/** @var OptionsResolver $this */
|
||||
if (!$this->isDefined($option)) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist.', $option));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist.', $option));
|
||||
}
|
||||
|
||||
if (!\array_key_exists($option, $this->{$property})) {
|
||||
@@ -45,7 +45,7 @@ class OptionsResolverIntrospector
|
||||
*/
|
||||
public function getDefault(string $option): mixed
|
||||
{
|
||||
return ($this->get)('defaults', $option, sprintf('No default value was set for the "%s" option.', $option));
|
||||
return ($this->get)('defaults', $option, \sprintf('No default value was set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +55,7 @@ class OptionsResolverIntrospector
|
||||
*/
|
||||
public function getLazyClosures(string $option): array
|
||||
{
|
||||
return ($this->get)('lazy', $option, sprintf('No lazy closures were set for the "%s" option.', $option));
|
||||
return ($this->get)('lazy', $option, \sprintf('No lazy closures were set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ class OptionsResolverIntrospector
|
||||
*/
|
||||
public function getAllowedTypes(string $option): array
|
||||
{
|
||||
return ($this->get)('allowedTypes', $option, sprintf('No allowed types were set for the "%s" option.', $option));
|
||||
return ($this->get)('allowedTypes', $option, \sprintf('No allowed types were set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +75,7 @@ class OptionsResolverIntrospector
|
||||
*/
|
||||
public function getAllowedValues(string $option): array
|
||||
{
|
||||
return ($this->get)('allowedValues', $option, sprintf('No allowed values were set for the "%s" option.', $option));
|
||||
return ($this->get)('allowedValues', $option, \sprintf('No allowed values were set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +91,7 @@ class OptionsResolverIntrospector
|
||||
*/
|
||||
public function getNormalizers(string $option): array
|
||||
{
|
||||
return ($this->get)('normalizers', $option, sprintf('No normalizer was set for the "%s" option.', $option));
|
||||
return ($this->get)('normalizers', $option, \sprintf('No normalizer was set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,6 +99,16 @@ class OptionsResolverIntrospector
|
||||
*/
|
||||
public function getDeprecation(string $option): array
|
||||
{
|
||||
return ($this->get)('deprecated', $option, sprintf('No deprecation was set for the "%s" option.', $option));
|
||||
return ($this->get)('deprecated', $option, \sprintf('No deprecation was set for the "%s" option.', $option));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Closure[]
|
||||
*
|
||||
* @throws NoConfigurationException when no nested option is configured
|
||||
*/
|
||||
public function getNestedOptions(string $option): array
|
||||
{
|
||||
return ($this->get)('nested', $option, \sprintf('No nested option was set for the "%s" option.', $option));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,10 @@ use Symfony\Component\OptionsResolver\Exception\AccessException;
|
||||
|
||||
final class OptionConfigurator
|
||||
{
|
||||
private string $name;
|
||||
private OptionsResolver $resolver;
|
||||
|
||||
public function __construct(string $name, OptionsResolver $resolver)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->resolver = $resolver;
|
||||
public function __construct(
|
||||
private string $name,
|
||||
private OptionsResolver $resolver,
|
||||
) {
|
||||
$this->resolver->setDefined($name);
|
||||
}
|
||||
|
||||
@@ -146,4 +143,18 @@ final class OptionConfigurator
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines nested options.
|
||||
*
|
||||
* @param \Closure(OptionsResolver $resolver, Options $parent): void $nested
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function options(\Closure $nested): static
|
||||
{
|
||||
$this->resolver->setOptions($this->name, $nested);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
227
vendor/symfony/options-resolver/OptionsResolver.php
vendored
227
vendor/symfony/options-resolver/OptionsResolver.php
vendored
@@ -64,6 +64,13 @@ class OptionsResolver implements Options
|
||||
*/
|
||||
private array $nested = [];
|
||||
|
||||
/**
|
||||
* BC layer. Remove in Symfony 8.0.
|
||||
*
|
||||
* @var array<string, true>
|
||||
*/
|
||||
private array $deprecatedNestedOptions = [];
|
||||
|
||||
/**
|
||||
* The names of required options.
|
||||
*/
|
||||
@@ -178,20 +185,6 @@ class OptionsResolver implements Options
|
||||
* is spread across different locations of your code, such as base and
|
||||
* sub-classes.
|
||||
*
|
||||
* If you want to define nested options, you can pass a closure with the
|
||||
* following signature:
|
||||
*
|
||||
* $options->setDefault('database', function (OptionsResolver $resolver) {
|
||||
* $resolver->setDefined(['dbname', 'host', 'port', 'user', 'pass']);
|
||||
* }
|
||||
*
|
||||
* To get access to the parent options, add a second argument to the closure's
|
||||
* signature:
|
||||
*
|
||||
* function (OptionsResolver $resolver, Options $parent) {
|
||||
* // 'default' === $parent['connection']
|
||||
* }
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AccessException If called from a lazy option or normalizer
|
||||
@@ -226,13 +219,22 @@ class OptionsResolver implements Options
|
||||
$this->lazy[$option][] = $value;
|
||||
$this->defined[$option] = true;
|
||||
|
||||
// Make sure the option is processed and is not nested anymore
|
||||
unset($this->resolved[$option], $this->nested[$option]);
|
||||
// Make sure the option is processed
|
||||
unset($this->resolved[$option]);
|
||||
|
||||
// BC layer. Remove in Symfony 8.0.
|
||||
if (isset($this->deprecatedNestedOptions[$option])) {
|
||||
unset($this->nested[$option]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (isset($params[0]) && null !== ($type = $params[0]->getType()) && self::class === $type->getName() && (!isset($params[1]) || (($type = $params[1]->getType()) instanceof \ReflectionNamedType && Options::class === $type->getName()))) {
|
||||
// Remove in Symfony 8.0.
|
||||
if (isset($params[0]) && ($type = $params[0]->getType()) instanceof \ReflectionNamedType && self::class === $type->getName() && (!isset($params[1]) || (($type = $params[1]->getType()) instanceof \ReflectionNamedType && Options::class === $type->getName()))) {
|
||||
trigger_deprecation('symfony/options-resolver', '7.3', 'Defining nested options via "%s()" is deprecated and will be removed in Symfony 8.0, use "setOptions()" method instead.', __METHOD__);
|
||||
$this->deprecatedNestedOptions[$option] = true;
|
||||
|
||||
// Store closure for later evaluation
|
||||
$this->nested[$option][] = $value;
|
||||
$this->defaults[$option] = [];
|
||||
@@ -245,8 +247,13 @@ class OptionsResolver implements Options
|
||||
}
|
||||
}
|
||||
|
||||
// This option is not lazy nor nested anymore
|
||||
unset($this->lazy[$option], $this->nested[$option]);
|
||||
// This option is not lazy anymore
|
||||
unset($this->lazy[$option]);
|
||||
|
||||
// BC layer. Remove in Symfony 8.0.
|
||||
if (isset($this->deprecatedNestedOptions[$option])) {
|
||||
unset($this->nested[$option]);
|
||||
}
|
||||
|
||||
// Yet undefined options can be marked as resolved, because we only need
|
||||
// to resolve options with lazy closures, normalizers or validation
|
||||
@@ -403,6 +410,30 @@ class OptionsResolver implements Options
|
||||
return array_keys($this->defined);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines nested options.
|
||||
*
|
||||
* @param \Closure(self $resolver, Options $parent): void $nested
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setOptions(string $option, \Closure $nested): static
|
||||
{
|
||||
if ($this->locked) {
|
||||
throw new AccessException('Nested options cannot be defined from a lazy option or normalizer.');
|
||||
}
|
||||
|
||||
// Store closure for later evaluation
|
||||
$this->nested[$option][] = $nested;
|
||||
$this->defaults[$option] = [];
|
||||
$this->defined[$option] = true;
|
||||
|
||||
// Make sure the option is processed
|
||||
unset($this->resolved[$option]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isNested(string $option): bool
|
||||
{
|
||||
return isset($this->nested[$option]);
|
||||
@@ -438,11 +469,11 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist, defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist, defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
if (!\is_string($message) && !$message instanceof \Closure) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid type for deprecation message argument, expected string or \Closure, but got "%s".', get_debug_type($message)));
|
||||
throw new InvalidArgumentException(\sprintf('Invalid type for deprecation message argument, expected string or \Closure, but got "%s".', get_debug_type($message)));
|
||||
}
|
||||
|
||||
// ignore if empty string
|
||||
@@ -497,7 +528,7 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
$this->normalizers[$option] = [$normalizer];
|
||||
@@ -538,7 +569,7 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
if ($forcePrepend) {
|
||||
@@ -581,7 +612,7 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
$this->allowedValues[$option] = \is_array($allowedValues) ? $allowedValues : [$allowedValues];
|
||||
@@ -621,7 +652,7 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
if (!\is_array($allowedValues)) {
|
||||
@@ -661,7 +692,7 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
$this->allowedTypes[$option] = (array) $allowedTypes;
|
||||
@@ -695,7 +726,7 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
if (!isset($this->allowedTypes[$option])) {
|
||||
@@ -716,7 +747,7 @@ class OptionsResolver implements Options
|
||||
public function define(string $option): OptionConfigurator
|
||||
{
|
||||
if (isset($this->defined[$option])) {
|
||||
throw new OptionDefinitionException(sprintf('The option "%s" is already defined.', $option));
|
||||
throw new OptionDefinitionException(\sprintf('The option "%s" is already defined.', $option));
|
||||
}
|
||||
|
||||
return new OptionConfigurator($option, $this);
|
||||
@@ -737,7 +768,7 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
$this->info[$option] = $info;
|
||||
@@ -751,7 +782,7 @@ class OptionsResolver implements Options
|
||||
public function getInfo(string $option): ?string
|
||||
{
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
return $this->info[$option] ?? null;
|
||||
@@ -873,7 +904,7 @@ class OptionsResolver implements Options
|
||||
ksort($clone->defined);
|
||||
ksort($diff);
|
||||
|
||||
throw new UndefinedOptionsException(sprintf((\count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Defined options are: "%s".', $this->formatOptions(array_keys($diff)), implode('", "', array_keys($clone->defined))));
|
||||
throw new UndefinedOptionsException(\sprintf((\count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Defined options are: "%s".', $this->formatOptions(array_keys($diff)), implode('", "', array_keys($clone->defined))));
|
||||
}
|
||||
|
||||
// Override options set by the user
|
||||
@@ -893,7 +924,7 @@ class OptionsResolver implements Options
|
||||
if (\count($diff) > 0) {
|
||||
ksort($diff);
|
||||
|
||||
throw new MissingOptionsException(sprintf(\count($diff) > 1 ? 'The required options "%s" are missing.' : 'The required option "%s" is missing.', $this->formatOptions(array_keys($diff))));
|
||||
throw new MissingOptionsException(\sprintf(\count($diff) > 1 ? 'The required options "%s" are missing.' : 'The required option "%s" is missing.', $this->formatOptions(array_keys($diff))));
|
||||
}
|
||||
|
||||
// Lock the container
|
||||
@@ -939,26 +970,42 @@ class OptionsResolver implements Options
|
||||
// Check whether the option is set at all
|
||||
if (!isset($this->defaults[$option]) && !\array_key_exists($option, $this->defaults)) {
|
||||
if (!isset($this->defined[$option])) {
|
||||
throw new NoSuchOptionException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
throw new NoSuchOptionException(\sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
|
||||
}
|
||||
|
||||
throw new NoSuchOptionException(sprintf('The optional option "%s" has no value set. You should make sure it is set with "isset" before reading it.', $this->formatOptions([$option])));
|
||||
throw new NoSuchOptionException(\sprintf('The optional option "%s" has no value set. You should make sure it is set with "isset" before reading it.', $this->formatOptions([$option])));
|
||||
}
|
||||
|
||||
$value = $this->defaults[$option];
|
||||
|
||||
// Resolve the option if the default value is lazily evaluated
|
||||
if (isset($this->lazy[$option])) {
|
||||
// If the closure is already being called, we have a cyclic dependency
|
||||
if (isset($this->calling[$option])) {
|
||||
throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
}
|
||||
|
||||
$this->calling[$option] = true;
|
||||
try {
|
||||
foreach ($this->lazy[$option] as $closure) {
|
||||
$value = $closure($this, $value);
|
||||
}
|
||||
} finally {
|
||||
unset($this->calling[$option]);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve the option if it is a nested definition
|
||||
if (isset($this->nested[$option])) {
|
||||
// If the closure is already being called, we have a cyclic dependency
|
||||
if (isset($this->calling[$option])) {
|
||||
throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
}
|
||||
|
||||
if (!\is_array($value)) {
|
||||
throw new InvalidOptionsException(sprintf('The nested option "%s" with value %s is expected to be of type array, but is of type "%s".', $this->formatOptions([$option]), $this->formatValue($value), get_debug_type($value)));
|
||||
throw new InvalidOptionsException(\sprintf('The nested option "%s" with value %s is expected to be of type array, but is of type "%s".', $this->formatOptions([$option]), $this->formatValue($value), get_debug_type($value)));
|
||||
}
|
||||
|
||||
// The following section must be protected from cyclic calls.
|
||||
$this->calling[$option] = true;
|
||||
try {
|
||||
$resolver = new self();
|
||||
@@ -973,7 +1020,7 @@ class OptionsResolver implements Options
|
||||
$values = [];
|
||||
foreach ($value as $index => $prototypeValue) {
|
||||
if (!\is_array($prototypeValue)) {
|
||||
throw new InvalidOptionsException(sprintf('The value of the option "%s" is expected to be of type array of array, but is of type array of "%s".', $this->formatOptions([$option]), get_debug_type($prototypeValue)));
|
||||
throw new InvalidOptionsException(\sprintf('The value of the option "%s" is expected to be of type array of array, but is of type array of "%s".', $this->formatOptions([$option]), get_debug_type($prototypeValue)));
|
||||
}
|
||||
|
||||
$resolver->prototypeIndex = $index;
|
||||
@@ -989,29 +1036,6 @@ class OptionsResolver implements Options
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve the option if the default value is lazily evaluated
|
||||
if (isset($this->lazy[$option])) {
|
||||
// If the closure is already being called, we have a cyclic
|
||||
// dependency
|
||||
if (isset($this->calling[$option])) {
|
||||
throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
}
|
||||
|
||||
// The following section must be protected from cyclic
|
||||
// calls. Set $calling for the current $option to detect a cyclic
|
||||
// dependency
|
||||
// BEGIN
|
||||
$this->calling[$option] = true;
|
||||
try {
|
||||
foreach ($this->lazy[$option] as $closure) {
|
||||
$value = $closure($this, $value);
|
||||
}
|
||||
} finally {
|
||||
unset($this->calling[$option]);
|
||||
}
|
||||
// END
|
||||
}
|
||||
|
||||
// Validate the type of the resolved option
|
||||
if (isset($this->allowedTypes[$option])) {
|
||||
$valid = true;
|
||||
@@ -1030,10 +1054,10 @@ class OptionsResolver implements Options
|
||||
$allowedContainsArrayType = \count(array_filter($this->allowedTypes[$option], static fn ($item) => str_ends_with($item, '[]'))) > 0;
|
||||
|
||||
if (\is_array($value) && $allowedContainsArrayType) {
|
||||
throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but one of the elements is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes));
|
||||
throw new InvalidOptionsException(\sprintf('The option "%s" with value %s is expected to be of type "%s", but one of the elements is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes));
|
||||
}
|
||||
|
||||
throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes));
|
||||
throw new InvalidOptionsException(\sprintf('The option "%s" with value %s is expected to be of type "%s", but is of type "%s".', $this->formatOptions([$option]), $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1062,21 +1086,21 @@ class OptionsResolver implements Options
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
$message = sprintf(
|
||||
$message = \sprintf(
|
||||
'The option "%s" with value %s is invalid.',
|
||||
$this->formatOptions([$option]),
|
||||
$this->formatValue($value)
|
||||
);
|
||||
|
||||
if (\count($printableAllowedValues) > 0) {
|
||||
$message .= sprintf(
|
||||
$message .= \sprintf(
|
||||
' Accepted values are: %s.',
|
||||
$this->formatValues($printableAllowedValues)
|
||||
);
|
||||
}
|
||||
|
||||
if (isset($this->info[$option])) {
|
||||
$message .= sprintf(' Info: %s.', $this->info[$option]);
|
||||
$message .= \sprintf(' Info: %s.', $this->info[$option]);
|
||||
}
|
||||
|
||||
throw new InvalidOptionsException($message);
|
||||
@@ -1092,13 +1116,13 @@ class OptionsResolver implements Options
|
||||
if ($message instanceof \Closure) {
|
||||
// If the closure is already being called, we have a cyclic dependency
|
||||
if (isset($this->calling[$option])) {
|
||||
throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
}
|
||||
|
||||
$this->calling[$option] = true;
|
||||
try {
|
||||
if (!\is_string($message = $message($this, $value))) {
|
||||
throw new InvalidOptionsException(sprintf('Invalid type for deprecation message, expected string but got "%s", return an empty string to ignore.', get_debug_type($message)));
|
||||
throw new InvalidOptionsException(\sprintf('Invalid type for deprecation message, expected string but got "%s", return an empty string to ignore.', get_debug_type($message)));
|
||||
}
|
||||
} finally {
|
||||
unset($this->calling[$option]);
|
||||
@@ -1115,7 +1139,7 @@ class OptionsResolver implements Options
|
||||
// If the closure is already being called, we have a cyclic
|
||||
// dependency
|
||||
if (isset($this->calling[$option])) {
|
||||
throw new OptionDefinitionException(sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
|
||||
}
|
||||
|
||||
// The following section must be protected from cyclic
|
||||
@@ -1139,8 +1163,29 @@ class OptionsResolver implements Options
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function verifyTypes(string $type, mixed $value, array &$invalidTypes, int $level = 0): bool
|
||||
private function verifyTypes(string $type, mixed $value, ?array &$invalidTypes = null, int $level = 0): bool
|
||||
{
|
||||
$type = trim($type);
|
||||
$allowedTypes = $this->splitOutsideParenthesis($type);
|
||||
if (\count($allowedTypes) > 1) {
|
||||
foreach ($allowedTypes as $allowedType) {
|
||||
if ($this->verifyTypes($allowedType, $value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (\is_array($invalidTypes) && (!$invalidTypes || $level > 0)) {
|
||||
$invalidTypes[get_debug_type($value)] = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$type = $allowedTypes[0];
|
||||
if (str_starts_with($type, '(') && str_ends_with($type, ')')) {
|
||||
return $this->verifyTypes(substr($type, 1, -1), $value, $invalidTypes, $level);
|
||||
}
|
||||
|
||||
if (\is_array($value) && str_ends_with($type, '[]')) {
|
||||
$type = substr($type, 0, -2);
|
||||
$valid = true;
|
||||
@@ -1158,13 +1203,47 @@ class OptionsResolver implements Options
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!$invalidTypes || $level > 0) {
|
||||
if (\is_array($invalidTypes) && (!$invalidTypes || $level > 0)) {
|
||||
$invalidTypes[get_debug_type($value)] = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
*/
|
||||
private function splitOutsideParenthesis(string $type): array
|
||||
{
|
||||
$parts = [];
|
||||
$currentPart = '';
|
||||
$parenthesisLevel = 0;
|
||||
|
||||
$typeLength = \strlen($type);
|
||||
for ($i = 0; $i < $typeLength; ++$i) {
|
||||
$char = $type[$i];
|
||||
|
||||
if ('(' === $char) {
|
||||
++$parenthesisLevel;
|
||||
} elseif (')' === $char) {
|
||||
--$parenthesisLevel;
|
||||
}
|
||||
|
||||
if ('|' === $char && 0 === $parenthesisLevel) {
|
||||
$parts[] = $currentPart;
|
||||
$currentPart = '';
|
||||
} else {
|
||||
$currentPart .= $char;
|
||||
}
|
||||
}
|
||||
|
||||
if ('' !== $currentPart) {
|
||||
$parts[] = $currentPart;
|
||||
}
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a resolved option with the given name exists.
|
||||
*
|
||||
@@ -1293,14 +1372,14 @@ class OptionsResolver implements Options
|
||||
if ($this->parentsOptions) {
|
||||
$prefix = array_shift($this->parentsOptions);
|
||||
if ($this->parentsOptions) {
|
||||
$prefix .= sprintf('[%s]', implode('][', $this->parentsOptions));
|
||||
$prefix .= \sprintf('[%s]', implode('][', $this->parentsOptions));
|
||||
}
|
||||
|
||||
if ($this->prototype && null !== $this->prototypeIndex) {
|
||||
$prefix .= sprintf('[%s]', $this->prototypeIndex);
|
||||
$prefix .= \sprintf('[%s]', $this->prototypeIndex);
|
||||
}
|
||||
|
||||
$options = array_map(static fn (string $option): string => sprintf('%s[%s]', $prefix, $option), $options);
|
||||
$options = array_map(static fn (string $option): string => \sprintf('%s[%s]', $prefix, $option), $options);
|
||||
}
|
||||
|
||||
return implode('", "', $options);
|
||||
|
||||
Reference in New Issue
Block a user