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

[OptionsResolver] Implemented policies for treating unknown/missing options #10574

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions 8 src/Symfony/Component/OptionsResolver/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CHANGELOG
=========

2.5.0
-----

* added flags FORBID_UNKNOWN, REMOVE_UNKNOWN, IGNORE_UNKNOWN, FORBID_MISSING
and IGNORE_MISSING to OptionsResolverInterface
25 changes: 20 additions & 5 deletions 25 src/Symfony/Component/OptionsResolver/OptionsResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,25 @@ public function isRequired($option)
/**
* {@inheritdoc}
*/
public function resolve(array $options = array())
public function resolve(array $options = array(), $flags = 0)
{
$this->validateOptionsExistence($options);
$this->validateOptionsCompleteness($options);
if (!($flags & (self::FORBID_UNKNOWN | self::REMOVE_UNKNOWN | self::IGNORE_UNKNOWN))) {
$flags |= self::FORBID_UNKNOWN;
}

if (!($flags & (self::FORBID_MISSING | self::IGNORE_MISSING))) {
$flags |= self::FORBID_MISSING;
}

if ($flags & self::FORBID_UNKNOWN) {
$this->validateOptionsExistence($options);
} elseif ($flags & self::REMOVE_UNKNOWN) {
$options = array_intersect_key($options, $this->knownOptions);
}

if ($flags & self::FORBID_MISSING) {
$this->validateOptionsCompleteness($options);
}

// Make sure this method can be called multiple times
$combinedOptions = clone $this->defaultOptions;
Expand All @@ -240,7 +255,7 @@ public function resolve(array $options = array())
* Validates that the given option names exist and throws an exception
* otherwise.
*
* @param array $options An list of option names as keys.
* @param array $options A list of option names as keys.
*
* @throws InvalidOptionsException If any of the options has not been defined.
*/
Expand All @@ -264,7 +279,7 @@ private function validateOptionsExistence(array $options)
* Validates that all required options are given and throws an exception
* otherwise.
*
* @param array $options An list of option names as keys.
* @param array $options A list of option names as keys.
*
* @throws MissingOptionsException If a required option is missing.
*/
Expand Down
31 changes: 29 additions & 2 deletions 31 src/Symfony/Component/OptionsResolver/OptionsResolverInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@
*/
interface OptionsResolverInterface
{
/**
* Throw an exception if unknown options are passed to {@link resolve()}.
*/
const FORBID_UNKNOWN = 1;

/**
* Remove unknown options passed to {@link resolve()}.
*/
const REMOVE_UNKNOWN = 2;

/**
* Ignore unknown options passed to {@link resolve()}.
*/
const IGNORE_UNKNOWN = 4;

/**
* Throw an exception if a required option is missing in {@link resolve()}.
*/
const FORBID_MISSING = 32;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

16 missing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And what about 8?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left them out by intention to allow further "UNKNOWN" values to be added (if needed).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also add them at the end with higher values if needed


/**
* Ignore missing required options in {@link resolve()}.
*/
const IGNORE_MISSING = 64;

/**
* Sets default option values.
*
Expand Down Expand Up @@ -195,7 +220,9 @@ public function isRequired($option);
/**
* Returns the combination of the default and the passed options.
*
* @param array $options The custom option values.
* @param array $options The custom option values.
* @param integer $flags A combination of the flag constants in this
* interface.
*
* @return array A list of options and their values.
*
Expand All @@ -206,5 +233,5 @@ public function isRequired($option);
* @throws Exception\OptionDefinitionException If a cyclic dependency is detected
* between two lazy options.
*/
public function resolve(array $options = array());
public function resolve(array $options = array(), $flags = 0);
}
110 changes: 109 additions & 1 deletion 110 src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Component\OptionsResolver\Tests;

use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\OptionsResolver\Options;

Expand Down Expand Up @@ -175,7 +176,7 @@ public function testResolveLazyReplaceDefaults()
/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
*/
public function testResolveFailsIfNonExistingOption()
public function testResolveFailsIfUnknownOption()
{
$this->resolver->setDefaults(array(
'one' => '1',
Expand All @@ -194,6 +195,57 @@ public function testResolveFailsIfNonExistingOption()
));
}

public function testResolveRemovesUnknownOptionIfFlagIsSet()
{
$this->resolver->setDefaults(array(
'one' => '1',
));

$this->resolver->setRequired(array(
'two',
));

$this->resolver->setOptional(array(
'three',
));

$options = $this->resolver->resolve(array(
'foo' => 'bar',
'two' => '20',
), OptionsResolverInterface::REMOVE_UNKNOWN);

$this->assertEquals(array(
'one' => '1',
'two' => '20'
), $options);
}

public function testResolveIgnoresUnknownOptionsIfFlagIsSet()
{
$this->resolver->setDefaults(array(
'one' => '1',
));

$this->resolver->setRequired(array(
'two',
));

$this->resolver->setOptional(array(
'three',
));

$options = $this->resolver->resolve(array(
'foo' => 'bar',
'two' => '20',
), OptionsResolverInterface::IGNORE_UNKNOWN);

$this->assertEquals(array(
'one' => '1',
'foo' => 'bar',
'two' => '20',
), $options);
}

/**
* @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
*/
Expand All @@ -212,6 +264,25 @@ public function testResolveFailsIfMissingRequiredOption()
));
}

public function testResolveIgnoresMissingRequiredOptionIfFlagIsSet()
{
$this->resolver->setRequired(array(
'one',
));

$this->resolver->setDefaults(array(
'two' => '2',
));

$options = $this->resolver->resolve(array(
'two' => '20',
), OptionsResolverInterface::IGNORE_MISSING);

$this->assertEquals(array(
'two' => '20',
), $options);
}

public function testResolveSucceedsIfOptionValueAllowed()
{
$this->resolver->setDefaults(array(
Expand Down Expand Up @@ -717,4 +788,41 @@ public function testClone()
'three' => '3',
), $clone->resolve());
}

public function testRemoveUnknownOption()
{
$this->resolver->setDefaults(array(
'one' => 'default',
'two' => 'default'
));

$options = $this->resolver->resolve(array(
'one' => 'keep',
'three' => 'remove'
), OptionsResolverInterface::REMOVE_UNKNOWN);

$this->assertEquals($options, array(
'one' => 'keep',
'two' => 'default'
));
}

public function testIgnoreUnknownOption()
{
$this->resolver->setDefaults(array(
'one' => 'default',
'two' => 'default'
));

$options = $this->resolver->resolve(array(
'one' => 'keep',
'three' => 'ignored'
), OptionsResolverInterface::IGNORE_UNKNOWN);

$this->assertEquals($options, array(
'one' => 'keep',
'two' => 'default',
'three' => 'ignored'
));
}
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.