diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php
index 0feeeddfa7..4605822ad3 100644
--- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php
+++ b/src/Symfony/Component/OptionsResolver/OptionsResolver.php
@@ -47,6 +47,12 @@ class OptionsResolver
*/
private $allowedValues = array();
+ /**
+ * A list of filters transforming each resolved options.
+ * @var array
+ */
+ private $filters = array();
+
/**
* Creates a new instance.
*/
@@ -58,12 +64,23 @@ class OptionsResolver
/**
* Sets default option values.
*
- * @param array $defaultValues A list of option names as keys and default values
- * as values. The option values may be closures
- * of the following signatures:
+ * The options can either be values of any types or closures that
+ * evaluate the option value lazily. These closures must have one
+ * of the following signatures:
*
- * - function (Options $options)
- * - function (Options $options, $previousValue)
+ *
+ * function (Options $options)
+ * function (Options $options, $value)
+ *
+ *
+ * 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.
*/
@@ -81,16 +98,13 @@ class OptionsResolver
/**
* 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
* performance if the previous default value is calculated by an expensive
* closure.
*
- * @param array $defaultValues A list of option names as keys and default values
- * as values. The option values may be closures
- * of the following signature:
- *
- * - function (Options $options)
+ * @param array $defaultValues A list of option names as keys and default
+ * values or closures as values.
*
* @return OptionsResolver The resolver instance.
*/
@@ -208,6 +222,32 @@ class OptionsResolver
return $this;
}
+ /**
+ * Sets filters that are applied on resolved options.
+ *
+ * The filters should be closures with the following signature:
+ *
+ *
+ * function (Options $options, $value)
+ *
+ *
+ * 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.
*
@@ -264,6 +304,11 @@ class OptionsResolver
$combinedOptions->set($option, $value);
}
+ // Apply filters
+ foreach ($this->filters as $option => $filter) {
+ $combinedOptions->overload($option, $filter);
+ }
+
// Resolve options
$resolvedOptions = $combinedOptions->all();
diff --git a/src/Symfony/Component/OptionsResolver/Tests/OptionResolverTest.php b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php
similarity index 92%
rename from src/Symfony/Component/OptionsResolver/Tests/OptionResolverTest.php
rename to src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php
index ef68c7f1e1..76d1611a8b 100644
--- a/src/Symfony/Component/OptionsResolver/Tests/OptionResolverTest.php
+++ b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php
@@ -373,6 +373,36 @@ class OptionsResolverTest extends \PHPUnit_Framework_TestCase
$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()
{
$this->resolver->setRequired(array(