Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fb70e0a

Browse filesBrowse files
committed
minor #30442 [OptionsResolver] Fix an error message to be more accurate (dimabory)
This PR was merged into the 3.4 branch. Discussion ---------- [OptionsResolver] Fix an error message to be more accurate | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #30432 | License | MIT | Doc PR | See #30432 for more details: > **Symfony version(s) affected**: 3.4, maybe other versions too (not tested) > > **Description** > Error message when allowedTypes is an array contains `[]` but should not: > `The option "testme" with value array is expected to be of type "string[]", but one of the elements is of type "integer[]".` > It should be: > `The option "testme" with value array is expected to be of type "string[]", but one of the elements is of type "integer".` > > **How to reproduce** > > ``` > $resolver = (new OptionsResolver()) > ->setDefault('testme', []) > ->setAllowedTypes('testme', ['string[]']) > ->resolve(['testme' => ['test', 12]]); > ``` In addition I changed an error message to be more accurate if provided more than one incorrect value: > [...] is expected to be of type "integer[][]", but is of type "integer|boolean|string". Commits ------- 7fa2fc2 #30432 fix an error message
2 parents 2a5c755 + 7fa2fc2 commit fb70e0a
Copy full SHA for fb70e0a

File tree

Expand file treeCollapse file tree

2 files changed

+38
-27
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+38
-27
lines changed

‎src/Symfony/Component/OptionsResolver/OptionsResolver.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/OptionsResolver.php
+22-18Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ public function offsetGet($option)
734734

735735
// Validate the type of the resolved option
736736
if (isset($this->allowedTypes[$option])) {
737-
$valid = false;
737+
$valid = true;
738738
$invalidTypes = [];
739739

740740
foreach ($this->allowedTypes[$option] as $type) {
@@ -746,13 +746,22 @@ public function offsetGet($option)
746746
}
747747

748748
if (!$valid) {
749-
$keys = array_keys($invalidTypes);
749+
$fmtActualValue = $this->formatValue($value);
750+
$fmtAllowedTypes = implode('" or "', $this->allowedTypes[$option]);
751+
$fmtProvidedTypes = implode('|', array_keys($invalidTypes));
752+
753+
$allowedContainsArrayType = \count(array_filter(
754+
$this->allowedTypes[$option],
755+
function ($item) {
756+
return '[]' === substr(isset(self::$typeAliases[$item]) ? self::$typeAliases[$item] : $item, -2);
757+
}
758+
)) > 0;
750759

751-
if (1 === \count($keys) && '[]' === substr($keys[0], -2)) {
752-
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".', $option, $this->formatValue($value), implode('" or "', $this->allowedTypes[$option]), $keys[0]));
760+
if (\is_array($value) && $allowedContainsArrayType) {
761+
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".', $option, $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes));
753762
}
754763

755-
throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but is of type "%s".', $option, $this->formatValue($value), implode('" or "', $this->allowedTypes[$option]), implode('|', array_keys($invalidTypes))));
764+
throw new InvalidOptionsException(sprintf('The option "%s" with value %s is expected to be of type "%s", but is of type "%s".', $option, $fmtActualValue, $fmtAllowedTypes, $fmtProvidedTypes));
756765
}
757766
}
758767

@@ -858,37 +867,32 @@ private function verifyArrayType($type, array $value, array &$invalidTypes, $lev
858867
{
859868
$type = substr($type, 0, -2);
860869

861-
$suffix = '[]';
862-
while (\strlen($suffix) <= $level * 2) {
863-
$suffix .= '[]';
864-
}
865-
866870
if ('[]' === substr($type, -2)) {
867871
$success = true;
868872
foreach ($value as $item) {
869873
if (!\is_array($item)) {
870-
$invalidTypes[$this->formatTypeOf($item, null).$suffix] = true;
874+
$invalidTypes[$this->formatTypeOf($item, null)] = true;
871875

872-
return false;
873-
}
874-
875-
if (!$this->verifyArrayType($type, $item, $invalidTypes, $level + 1)) {
876+
$success = false;
877+
} elseif (!$this->verifyArrayType($type, $item, $invalidTypes, $level + 1)) {
876878
$success = false;
877879
}
878880
}
879881

880882
return $success;
881883
}
882884

885+
$valid = true;
886+
883887
foreach ($value as $item) {
884888
if (!self::isValueValidType($type, $item)) {
885-
$invalidTypes[$this->formatTypeOf($item, $type).$suffix] = $value;
889+
$invalidTypes[$this->formatTypeOf($item, $type)] = $value;
886890

887-
return false;
891+
$valid = false;
888892
}
889893
}
890894

891-
return true;
895+
return $valid;
892896
}
893897

894898
/**

‎src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php
+16-9Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ public function testFailIfSetAllowedTypesFromLazyOption()
466466
public function testResolveFailsIfInvalidTypedArray()
467467
{
468468
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
469-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[]", but one of the elements is of type "DateTime[]".');
469+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[]", but one of the elements is of type "DateTime".');
470470
$this->resolver->setDefined('foo');
471471
$this->resolver->setAllowedTypes('foo', 'int[]');
472472

@@ -486,9 +486,10 @@ public function testResolveFailsWithNonArray()
486486
public function testResolveFailsIfTypedArrayContainsInvalidTypes()
487487
{
488488
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
489-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[]", but one of the elements is of type "stdClass[]".');
489+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[]", but one of the elements is of type "stdClass|array|DateTime".');
490490
$this->resolver->setDefined('foo');
491491
$this->resolver->setAllowedTypes('foo', 'int[]');
492+
492493
$values = range(1, 5);
493494
$values[] = new \stdClass();
494495
$values[] = [];
@@ -501,7 +502,7 @@ public function testResolveFailsIfTypedArrayContainsInvalidTypes()
501502
public function testResolveFailsWithCorrectLevelsButWrongScalar()
502503
{
503504
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
504-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[][]", but one of the elements is of type "double[][]".');
505+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[][]", but one of the elements is of type "double".');
505506
$this->resolver->setDefined('foo');
506507
$this->resolver->setAllowedTypes('foo', 'int[][]');
507508

@@ -537,6 +538,11 @@ public function provideInvalidTypes()
537538
[42, 'string', 'The option "option" with value 42 is expected to be of type "string", but is of type "integer".'],
538539
[null, 'string', 'The option "option" with value null is expected to be of type "string", but is of type "NULL".'],
539540
['bar', '\stdClass', 'The option "option" with value "bar" is expected to be of type "\stdClass", but is of type "string".'],
541+
[['foo', 12], 'string[]', 'The option "option" with value array is expected to be of type "string[]", but one of the elements is of type "integer".'],
542+
[123, ['string[]', 'string'], 'The option "option" with value 123 is expected to be of type "string[]" or "string", but is of type "integer".'],
543+
[[null], ['string[]', 'string'], 'The option "option" with value array is expected to be of type "string[]" or "string", but one of the elements is of type "NULL".'],
544+
[['string', null], ['string[]', 'string'], 'The option "option" with value array is expected to be of type "string[]" or "string", but one of the elements is of type "NULL".'],
545+
[[\stdClass::class], ['string'], 'The option "option" with value array is expected to be of type "string", but is of type "array".'],
540546
];
541547
}
542548

@@ -585,6 +591,7 @@ public function testResolveSucceedsIfTypedArray()
585591
new \DateTime(),
586592
],
587593
];
594+
588595
$result = $this->resolver->resolve($data);
589596
$this->assertEquals($data, $result);
590597
}
@@ -1535,7 +1542,7 @@ public function testNested2Arrays()
15351542
public function testNestedArraysException()
15361543
{
15371544
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
1538-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "float[][][][]", but one of the elements is of type "integer[][][][]".');
1545+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "float[][][][]", but one of the elements is of type "integer".');
15391546
$this->resolver->setDefined('foo');
15401547
$this->resolver->setAllowedTypes('foo', 'float[][][][]');
15411548

@@ -1553,7 +1560,7 @@ public function testNestedArraysException()
15531560
public function testNestedArrayException1()
15541561
{
15551562
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
1556-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[][]", but one of the elements is of type "boolean[][]".');
1563+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[][]", but one of the elements is of type "boolean|string|array".');
15571564
$this->resolver->setDefined('foo');
15581565
$this->resolver->setAllowedTypes('foo', 'int[][]');
15591566
$this->resolver->resolve([
@@ -1566,7 +1573,7 @@ public function testNestedArrayException1()
15661573
public function testNestedArrayException2()
15671574
{
15681575
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
1569-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[][]", but one of the elements is of type "boolean[][]".');
1576+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "int[][]", but one of the elements is of type "boolean|string|array".');
15701577
$this->resolver->setDefined('foo');
15711578
$this->resolver->setAllowedTypes('foo', 'int[][]');
15721579
$this->resolver->resolve([
@@ -1579,7 +1586,7 @@ public function testNestedArrayException2()
15791586
public function testNestedArrayException3()
15801587
{
15811588
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
1582-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "string[][][]", but one of the elements is of type "string[][]".');
1589+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "string[][][]", but one of the elements is of type "string|integer".');
15831590
$this->resolver->setDefined('foo');
15841591
$this->resolver->setAllowedTypes('foo', 'string[][][]');
15851592
$this->resolver->resolve([
@@ -1592,7 +1599,7 @@ public function testNestedArrayException3()
15921599
public function testNestedArrayException4()
15931600
{
15941601
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
1595-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "string[][][]", but one of the elements is of type "integer[][][]".');
1602+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "string[][][]", but one of the elements is of type "integer".');
15961603
$this->resolver->setDefined('foo');
15971604
$this->resolver->setAllowedTypes('foo', 'string[][][]');
15981605
$this->resolver->resolve([
@@ -1606,7 +1613,7 @@ public function testNestedArrayException4()
16061613
public function testNestedArrayException5()
16071614
{
16081615
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
1609-
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "string[]", but one of the elements is of type "array[]".');
1616+
$this->expectExceptionMessage('The option "foo" with value array is expected to be of type "string[]", but one of the elements is of type "array".');
16101617
$this->resolver->setDefined('foo');
16111618
$this->resolver->setAllowedTypes('foo', 'string[]');
16121619
$this->resolver->resolve([

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.