Skip to content

Commit db9884b

Browse files
committed
[OptionsResolver] add missing exception based on OutOfBoundsException and clarify message
1 parent f64bf61 commit db9884b

File tree

4 files changed

+82
-25
lines changed

4 files changed

+82
-25
lines changed

Exception/ExceptionInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace Symfony\Component\OptionsResolver\Exception;
1313

1414
/**
15-
* Marker interface for the Options component.
15+
* Marker interface for all exceptions thrown by the OptionsResolver component.
1616
*
1717
* @author Bernhard Schussek <[email protected]>
1818
*/

Exception/NoSuchOptionException.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\OptionsResolver\Exception;
13+
14+
/**
15+
* Thrown when trying to read an option that has no value set.
16+
*
17+
* When accessing optional options from within a lazy option or normalizer you should first
18+
* check whether the optional option is set. You can do this with `isset($options['optional'])`.
19+
* In contrast to the {@link UndefinedOptionsException}, this is a runtime exception that can
20+
* occur when evaluating lazy options.
21+
*
22+
* @author Tobias Schultze <http://tobion.de>
23+
*/
24+
class NoSuchOptionException extends \OutOfBoundsException implements ExceptionInterface
25+
{
26+
}

OptionsResolver.php

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\OptionsResolver\Exception\AccessException;
1515
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
1616
use Symfony\Component\OptionsResolver\Exception\MissingOptionsException;
17+
use Symfony\Component\OptionsResolver\Exception\NoSuchOptionException;
1718
use Symfony\Component\OptionsResolver\Exception\OptionDefinitionException;
1819
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
1920

@@ -155,7 +156,7 @@ public function setDefault($option, $value)
155156
// options could manipulate the state of the object, leading to
156157
// inconsistent results.
157158
if ($this->locked) {
158-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
159+
throw new AccessException('Default values cannot be set from a lazy option or normalizer.');
159160
}
160161

161162
// If an option is a closure that should be evaluated lazily, store it
@@ -248,7 +249,7 @@ public function hasDefault($option)
248249
public function setRequired($optionNames)
249250
{
250251
if ($this->locked) {
251-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
252+
throw new AccessException('Options cannot be made required from a lazy option or normalizer.');
252253
}
253254

254255
foreach ((array) $optionNames as $key => $option) {
@@ -329,7 +330,7 @@ public function getMissingOptions()
329330
public function setDefined($optionNames)
330331
{
331332
if ($this->locked) {
332-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
333+
throw new AccessException('Options cannot be defined from a lazy option or normalizer.');
333334
}
334335

335336
foreach ((array) $optionNames as $key => $option) {
@@ -397,12 +398,12 @@ public function getDefinedOptions()
397398
public function setNormalizer($option, \Closure $normalizer)
398399
{
399400
if ($this->locked) {
400-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
401+
throw new AccessException('Normalizers cannot be set from a lazy option or normalizer.');
401402
}
402403

403404
if (!isset($this->defined[$option])) {
404405
throw new UndefinedOptionsException(sprintf(
405-
'The option "%s" does not exist. Known options are: "%s"',
406+
'The option "%s" does not exist. Known options are: "%s".',
406407
$option,
407408
implode('", "', array_keys($this->defined))
408409
));
@@ -452,7 +453,7 @@ public function setNormalizers(array $normalizers)
452453
public function setAllowedValues($option, $allowedValues = null)
453454
{
454455
if ($this->locked) {
455-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
456+
throw new AccessException('Allowed values cannot be set from a lazy option or normalizer.');
456457
}
457458

458459
// BC
@@ -466,7 +467,7 @@ public function setAllowedValues($option, $allowedValues = null)
466467

467468
if (!isset($this->defined[$option])) {
468469
throw new UndefinedOptionsException(sprintf(
469-
'The option "%s" does not exist. Known options are: "%s"',
470+
'The option "%s" does not exist. Known options are: "%s".',
470471
$option,
471472
implode('", "', array_keys($this->defined))
472473
));
@@ -506,7 +507,7 @@ public function setAllowedValues($option, $allowedValues = null)
506507
public function addAllowedValues($option, $allowedValues = null)
507508
{
508509
if ($this->locked) {
509-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
510+
throw new AccessException('Allowed values cannot be added from a lazy option or normalizer.');
510511
}
511512

512513
// BC
@@ -520,7 +521,7 @@ public function addAllowedValues($option, $allowedValues = null)
520521

521522
if (!isset($this->defined[$option])) {
522523
throw new UndefinedOptionsException(sprintf(
523-
'The option "%s" does not exist. Known options are: "%s"',
524+
'The option "%s" does not exist. Known options are: "%s".',
524525
$option,
525526
implode('", "', array_keys($this->defined))
526527
));
@@ -558,7 +559,7 @@ public function addAllowedValues($option, $allowedValues = null)
558559
public function setAllowedTypes($option, $allowedTypes = null)
559560
{
560561
if ($this->locked) {
561-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
562+
throw new AccessException('Allowed types cannot be set from a lazy option or normalizer.');
562563
}
563564

564565
// BC
@@ -572,7 +573,7 @@ public function setAllowedTypes($option, $allowedTypes = null)
572573

573574
if (!isset($this->defined[$option])) {
574575
throw new UndefinedOptionsException(sprintf(
575-
'The option "%s" does not exist. Known options are: "%s"',
576+
'The option "%s" does not exist. Known options are: "%s".',
576577
$option,
577578
implode('", "', array_keys($this->defined))
578579
));
@@ -606,7 +607,7 @@ public function setAllowedTypes($option, $allowedTypes = null)
606607
public function addAllowedTypes($option, $allowedTypes = null)
607608
{
608609
if ($this->locked) {
609-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
610+
throw new AccessException('Allowed types cannot be added from a lazy option or normalizer.');
610611
}
611612

612613
// BC
@@ -620,7 +621,7 @@ public function addAllowedTypes($option, $allowedTypes = null)
620621

621622
if (!isset($this->defined[$option])) {
622623
throw new UndefinedOptionsException(sprintf(
623-
'The option "%s" does not exist. Known options are: "%s"',
624+
'The option "%s" does not exist. Known options are: "%s".',
624625
$option,
625626
implode('", "', array_keys($this->defined))
626627
));
@@ -652,7 +653,7 @@ public function addAllowedTypes($option, $allowedTypes = null)
652653
public function remove($optionNames)
653654
{
654655
if ($this->locked) {
655-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
656+
throw new AccessException('Options cannot be removed from a lazy option or normalizer.');
656657
}
657658

658659
foreach ((array) $optionNames as $option) {
@@ -679,7 +680,7 @@ public function remove($optionNames)
679680
public function clear()
680681
{
681682
if ($this->locked) {
682-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
683+
throw new AccessException('Options cannot be cleared from a lazy option or normalizer.');
683684
}
684685

685686
$this->defined = array();
@@ -715,12 +716,13 @@ public function clear()
715716
* @throws MissingOptionsException If a required option is missing
716717
* @throws OptionDefinitionException If there is a cyclic dependency between
717718
* lazy options and/or normalizers
719+
* @throws NoSuchOptionException If a lazy option reads an unavailable option
718720
* @throws AccessException If called from a lazy option or normalizer
719721
*/
720722
public function resolve(array $options = array())
721723
{
722724
if ($this->locked) {
723-
throw new AccessException('This method cannot be called from a lazy option or normalizer.');
725+
throw new AccessException('Options cannot be resolved from a lazy option or normalizer.');
724726
}
725727

726728
// Allow this method to be called multiple times
@@ -734,7 +736,7 @@ public function resolve(array $options = array())
734736
ksort($diff);
735737

736738
throw new UndefinedOptionsException(sprintf(
737-
(count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Known options are: "%s"',
739+
(count($diff) > 1 ? 'The options "%s" do not exist.' : 'The option "%s" does not exist.').' Known options are: "%s".',
738740
implode('", "', array_keys($diff)),
739741
implode('", "', array_keys($clone->defined))
740742
));
@@ -779,8 +781,8 @@ public function resolve(array $options = array())
779781
*
780782
* @throws AccessException If accessing this method outside of
781783
* {@link resolve()}
782-
* @throws \OutOfBoundsException If the option is not set
783-
* @throws InvalidOptionsException If an option doesn't fulfill the
784+
* @throws NoSuchOptionException If the option is not set
785+
* @throws InvalidOptionsException If the option doesn't fulfill the
784786
* specified validation rules
785787
* @throws OptionDefinitionException If there is a cyclic dependency between
786788
* lazy options and/or normalizers
@@ -798,7 +800,18 @@ public function offsetGet($option)
798800

799801
// Check whether the option is set at all
800802
if (!array_key_exists($option, $this->defaults)) {
801-
throw new \OutOfBoundsException(sprintf('The option "%s" was not set.', $option));
803+
if (!isset($this->defined[$option])) {
804+
throw new NoSuchOptionException(sprintf(
805+
'The option "%s" does not exist. Known options are: "%s".',
806+
$option,
807+
implode('", "', array_keys($this->defined))
808+
));
809+
}
810+
811+
throw new NoSuchOptionException(sprintf(
812+
'The optional option "%s" has no value set. You should make sure it is set with "isset" before reading it.',
813+
$option
814+
));
802815
}
803816

804817
$value = $this->defaults[$option];

Tests/OptionsResolver2Dot6Test.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,26 @@ protected function setUp()
3333

3434
/**
3535
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
36+
* @expectedExceptionMessage The option "foo" does not exist. Known options are: "a", "z".
3637
*/
3738
public function testResolveFailsIfNonExistingOption()
3839
{
39-
$resolver = new OptionsResolver();
40+
$this->resolver->setDefault('z', '1');
41+
$this->resolver->setDefault('a', '2');
4042

41-
$resolver->resolve(array('foo' => 'bar'));
43+
$this->resolver->resolve(array('foo' => 'bar'));
44+
}
45+
46+
/**
47+
* @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
48+
* @expectedExceptionMessage The options "baz", "foo", "ping" do not exist. Known options are: "a", "z".
49+
*/
50+
public function testResolveFailsIfMultipleNonExistingOptions()
51+
{
52+
$this->resolver->setDefault('z', '1');
53+
$this->resolver->setDefault('a', '2');
54+
55+
$this->resolver->resolve(array('ping' => 'pong', 'foo' => 'bar', 'baz' => 'bam'));
4256
}
4357

4458
/**
@@ -1390,10 +1404,13 @@ public function testArrayAccessUnsetNotSupported()
13901404
}
13911405

13921406
/**
1393-
* @expectedException \OutOfBoundsException
1407+
* @expectedException \Symfony\Component\OptionsResolver\Exception\NoSuchOptionException
1408+
* @expectedExceptionMessage The option "undefined" does not exist. Known options are: "foo", "lazy".
13941409
*/
13951410
public function testFailIfGetNonExisting()
13961411
{
1412+
$this->resolver->setDefault('foo', 'bar');
1413+
13971414
$this->resolver->setDefault('lazy', function (Options $options) {
13981415
$options['undefined'];
13991416
});
@@ -1402,7 +1419,8 @@ public function testFailIfGetNonExisting()
14021419
}
14031420

14041421
/**
1405-
* @expectedException \OutOfBoundsException
1422+
* @expectedException \Symfony\Component\OptionsResolver\Exception\NoSuchOptionException
1423+
* @expectedExceptionMessage The optional option "defined" has no value set. You should make sure it is set with "isset" before reading it.
14061424
*/
14071425
public function testFailIfGetDefinedButUnset()
14081426
{

0 commit comments

Comments
 (0)