symfony-cmf/RoutingAutoBundle — pull request #61 by WouterJ (2014-01-27 15:35:19+00:00)
Title: [WIP/POC] Implement Options Resolver

| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | yes
| Deprecations? | no
| Tests pass? | incomplete
| Fixed tickets | #20
| License | MIT
| Doc PR | todo

This PR tackles 3 problem of the current RoutingAuto implementation. Let me first sum up what those are and what needs to be done, then I'll try to give a small explaination about the code.

- Using the OptionsResolver component for the builder services
- Making builder services stateless
- Decoupling container and `Factory` and adding a `ContainerAwareFactory` to the bundle

### Todo

- [ ] Write docs
- [ ] Rewrite incomplete test, it doesn't make sense now
- [ ] Discuss the code, improve it and test it

### Making builder services stateless and implement the options resolver

Previously, a builder service was initialized with the `init` method, it would validate the options and save them to use it later. Then the `providePath` or `execute` method was called, which used the previously saved options to perform an action.

Instead of that, I decided to follow the Symfony Form component. The builder services are now stateless. This means they get initialized once and the same instance will be used in each builder unit.
The first time a builder service is used, its options resolver is configured with the possible options of the service. The options for the builder services within a builder unit are passed to the `BuilderUnit` class (in the Form component, this is a `ResolvedFormType` class). When the BuilderUnit class needs to execute and action or provide the path, it calls the correct service and passes the resolved options to it.

This means that the `BuilderUnit` now has the statefull things of the builder services.

### BC breaks

This change means a lot of BC breaks for builder services:

**Before**
````php
class FooPath implements PathActionInterface
{
protected $bar;
// ...
public function init(array $options)
{
if (!isset($options['bar'])) {
throw new MissingOptionException(...);
}

$this->bar = $options['bar'];
}

public function execute(RouteStack $routeStack)
{
$bar = $this->bar;
// ...
}
}
````

**After**
````php
class CreatePath extends AbstractPathAction
{
// ...
public function configureOptions(OptionsResolverInterface $resolver)
{
$resolver->setRequired(array('bar'));
}

public function execute(RouteStack $routeStack, array $options)
{
$bar = $options['bar'];
// ...
}
}
````