[OptionsResolver] Added method setFilters() for augmenting the final option values

This commit is contained in:
Bernhard Schussek 2012-05-23 15:59:31 +02:00
parent 45849ce306
commit 0af5f06703
2 changed files with 86 additions and 11 deletions

View File

@ -47,6 +47,12 @@ class OptionsResolver
*/ */
private $allowedValues = array(); private $allowedValues = array();
/**
* A list of filters transforming each resolved options.
* @var array
*/
private $filters = array();
/** /**
* Creates a new instance. * Creates a new instance.
*/ */
@ -58,12 +64,23 @@ class OptionsResolver
/** /**
* Sets default option values. * Sets default option values.
* *
* @param array $defaultValues A list of option names as keys and default values * The options can either be values of any types or closures that
* as values. The option values may be closures * evaluate the option value lazily. These closures must have one
* of the following signatures: * of the following signatures:
* *
* - function (Options $options) * <code>
* - function (Options $options, $previousValue) * function (Options $options)
* function (Options $options, $value)
* </code>
*
* The second parameter passed to the closure is the previously
* set default value, in case you are overwriting an existing
* default value.
*
* The closures should return the lazily created option value.
*
* @param array $defaultValues A list of option names as keys and default
* values or closures as values.
* *
* @return OptionsResolver The resolver instance. * @return OptionsResolver The resolver instance.
*/ */
@ -81,16 +98,13 @@ class OptionsResolver
/** /**
* Replaces default option values. * Replaces default option values.
* *
* Old defaults are erased, which means that closures passed here can't * Old defaults are erased, which means that closures passed here cannot
* access the previous default value. This may be useful to improve * access the previous default value. This may be useful to improve
* performance if the previous default value is calculated by an expensive * performance if the previous default value is calculated by an expensive
* closure. * closure.
* *
* @param array $defaultValues A list of option names as keys and default values * @param array $defaultValues A list of option names as keys and default
* as values. The option values may be closures * values or closures as values.
* of the following signature:
*
* - function (Options $options)
* *
* @return OptionsResolver The resolver instance. * @return OptionsResolver The resolver instance.
*/ */
@ -208,6 +222,32 @@ class OptionsResolver
return $this; return $this;
} }
/**
* Sets filters that are applied on resolved options.
*
* The filters should be closures with the following signature:
*
* <code>
* function (Options $options, $value)
* </code>
*
* The second parameter passed to the closure is the value of
* the option.
*
* The closure should return the filtered value.
*
* @param array $filters
* @return OptionsResolver
*/
public function setFilters(array $filters)
{
$this->validateOptionsExistence($filters);
$this->filters = array_replace($this->filters, $filters);
return $this;
}
/** /**
* Returns whether an option is known. * Returns whether an option is known.
* *
@ -264,6 +304,11 @@ class OptionsResolver
$combinedOptions->set($option, $value); $combinedOptions->set($option, $value);
} }
// Apply filters
foreach ($this->filters as $option => $filter) {
$combinedOptions->overload($option, $filter);
}
// Resolve options // Resolve options
$resolvedOptions = $combinedOptions->all(); $resolvedOptions = $combinedOptions->all();

View File

@ -373,6 +373,36 @@ class OptionsResolverTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($this->resolver->isRequired('foo')); $this->assertFalse($this->resolver->isRequired('foo'));
} }
public function testFiltersTransformFinalOptions()
{
$this->resolver->setDefaults(array(
'foo' => 'bar',
'bam' => 'baz',
));
$this->resolver->setFilters(array(
'foo' => function (Options $options, $value) {
return $options['bam'] . '[' . $value . ']';
},
));
$expected = array(
'foo' => 'baz[bar]',
'bam' => 'baz',
);
$this->assertEquals($expected, $this->resolver->resolve(array()));
$expected = array(
'foo' => 'boo[custom]',
'bam' => 'boo',
);
$this->assertEquals($expected, $this->resolver->resolve(array(
'foo' => 'custom',
'bam' => 'boo',
)));
}
public function testResolveWithoutOptionSucceedsIfRequiredAndDefaultValue() public function testResolveWithoutOptionSucceedsIfRequiredAndDefaultValue()
{ {
$this->resolver->setRequired(array( $this->resolver->setRequired(array(