2011-02-19 12:52:37 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is part of the Symfony package.
|
|
|
|
*
|
|
|
|
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Symfony\Component\Form;
|
|
|
|
|
2011-03-02 11:20:30 +00:00
|
|
|
use Symfony\Component\Form\Config\FieldConfigInterface;
|
2011-03-02 13:58:19 +00:00
|
|
|
use Symfony\Component\Form\Config\Loader\ConfigLoaderInterface;
|
|
|
|
use Symfony\Component\Form\Guesser\FieldGuesserInterface;
|
|
|
|
use Symfony\Component\Form\Guesser\FieldGuess;
|
2011-02-19 12:52:37 +00:00
|
|
|
|
2011-03-02 11:20:30 +00:00
|
|
|
class FormFactory implements FormFactoryInterface
|
2011-02-19 12:52:37 +00:00
|
|
|
{
|
2011-03-02 13:58:19 +00:00
|
|
|
private $configLoader;
|
|
|
|
|
|
|
|
private $guessers = array();
|
|
|
|
|
|
|
|
public function __construct(ConfigLoaderInterface $configLoader)
|
2011-02-19 12:52:37 +00:00
|
|
|
{
|
2011-03-02 13:58:19 +00:00
|
|
|
$this->configLoader = $configLoader;
|
|
|
|
}
|
2011-02-19 12:52:37 +00:00
|
|
|
|
2011-03-02 13:58:19 +00:00
|
|
|
public function addGuesser(FieldGuesserInterface $guesser)
|
|
|
|
{
|
|
|
|
$this->guessers[] = $guesser;
|
2011-02-19 12:52:37 +00:00
|
|
|
}
|
|
|
|
|
2011-03-17 10:03:10 +00:00
|
|
|
public function getInstance($identifier, $name = null, array $options = array())
|
2011-02-19 14:26:07 +00:00
|
|
|
{
|
2011-03-04 15:01:50 +00:00
|
|
|
// TODO $identifier can be FQN of a config class
|
|
|
|
|
2011-03-02 13:58:19 +00:00
|
|
|
$instance = null;
|
2011-03-02 11:20:30 +00:00
|
|
|
$hierarchy = array();
|
2011-02-21 22:40:12 +00:00
|
|
|
|
2011-03-02 15:00:31 +00:00
|
|
|
// TESTME
|
2011-03-17 10:03:10 +00:00
|
|
|
if (null === $name) {
|
|
|
|
$name = $identifier;
|
2011-03-02 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
2011-03-02 11:20:30 +00:00
|
|
|
while (null !== $identifier) {
|
|
|
|
// TODO check if identifier exists
|
2011-03-02 13:58:19 +00:00
|
|
|
$config = $this->configLoader->getConfig($identifier);
|
2011-03-02 11:20:30 +00:00
|
|
|
array_unshift($hierarchy, $config);
|
2011-03-17 10:03:10 +00:00
|
|
|
$instance = $instance ?: $config->createInstance($name);
|
2011-03-02 11:20:30 +00:00
|
|
|
$options = array_merge($config->getDefaultOptions($options), $options);
|
|
|
|
$identifier = $config->getParent($options);
|
2011-02-21 22:40:12 +00:00
|
|
|
}
|
2011-02-19 12:52:37 +00:00
|
|
|
|
2011-03-02 13:58:19 +00:00
|
|
|
// TODO check if instance exists
|
2011-02-19 16:30:19 +00:00
|
|
|
|
2011-03-02 11:20:30 +00:00
|
|
|
foreach ($hierarchy as $config) {
|
|
|
|
$config->configure($instance, $options);
|
2011-02-19 14:26:07 +00:00
|
|
|
}
|
|
|
|
|
2011-03-02 11:20:30 +00:00
|
|
|
return $instance;
|
2011-03-01 14:18:55 +00:00
|
|
|
}
|
2011-03-02 13:58:19 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritDoc
|
|
|
|
*/
|
|
|
|
public function getInstanceForProperty($class, $property, array $options = array())
|
|
|
|
{
|
|
|
|
// guess field class and options
|
|
|
|
$identifierGuess = $this->guess(function ($guesser) use ($class, $property) {
|
|
|
|
return $guesser->guessIdentifier($class, $property);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!$identifierGuess) {
|
|
|
|
throw new \RuntimeException(sprintf('No field could be guessed for property "%s" of class %s', $property, $class));
|
|
|
|
}
|
|
|
|
|
|
|
|
// guess maximum length
|
|
|
|
$maxLengthGuess = $this->guess(function ($guesser) use ($class, $property) {
|
|
|
|
return $guesser->guessMaxLength($class, $property);
|
|
|
|
});
|
|
|
|
|
|
|
|
// guess whether field is required
|
|
|
|
$requiredGuess = $this->guess(function ($guesser) use ($class, $property) {
|
|
|
|
return $guesser->guessRequired($class, $property);
|
|
|
|
});
|
|
|
|
|
|
|
|
// construct field
|
|
|
|
$identifier = $identifierGuess->getIdentifier();
|
|
|
|
|
|
|
|
// TODO all configs supporting the option "max_length" should receive
|
|
|
|
// it
|
|
|
|
if ($maxLengthGuess && $identifier == 'text') {
|
|
|
|
// TODO enable me again later
|
|
|
|
// $options = array_merge(array('max_length' => $maxLengthGuess->getValue()), $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($requiredGuess) {
|
|
|
|
$options = array_merge(array('required' => $requiredGuess->getValue()), $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
// user options may override guessed options
|
|
|
|
$options = array_merge($identifierGuess->getOptions(), $options);
|
|
|
|
|
|
|
|
return $this->getInstance($identifier, $property, $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Executes a closure for each guesser and returns the best guess from the
|
|
|
|
* return values
|
|
|
|
*
|
|
|
|
* @param \Closure $closure The closure to execute. Accepts a guesser as
|
|
|
|
* argument and should return a FieldFactoryGuess
|
|
|
|
* instance
|
|
|
|
* @return FieldFactoryGuess The guess with the highest confidence
|
|
|
|
*/
|
|
|
|
protected function guess(\Closure $closure)
|
|
|
|
{
|
|
|
|
$guesses = array();
|
|
|
|
|
|
|
|
foreach ($this->guessers as $guesser) {
|
|
|
|
if ($guess = $closure($guesser)) {
|
|
|
|
$guesses[] = $guess;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FieldGuess::getBestGuess($guesses);
|
|
|
|
}
|
2011-02-19 12:52:37 +00:00
|
|
|
}
|