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-18 15:20:00 +00:00
|
|
|
use Symfony\Component\Form\Type\FieldTypeInterface;
|
|
|
|
use Symfony\Component\Form\Type\Loader\TypeLoaderInterface;
|
2011-03-18 13:37:54 +00:00
|
|
|
use Symfony\Component\Form\FieldGuesser\FieldGuesserInterface;
|
|
|
|
use Symfony\Component\Form\FieldGuesser\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-18 15:20:00 +00:00
|
|
|
private $typeLoader;
|
2011-03-02 13:58:19 +00:00
|
|
|
|
|
|
|
private $guessers = array();
|
|
|
|
|
2011-03-18 15:20:00 +00:00
|
|
|
public function __construct(TypeLoaderInterface $typeLoader)
|
2011-02-19 12:52:37 +00:00
|
|
|
{
|
2011-03-18 15:20:00 +00:00
|
|
|
$this->typeLoader = $typeLoader;
|
2011-03-02 13:58:19 +00:00
|
|
|
}
|
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-18 15:20:00 +00:00
|
|
|
public function createBuilder($type, $name = null, array $options = array())
|
2011-02-19 14:26:07 +00:00
|
|
|
{
|
2011-03-18 15:20:00 +00:00
|
|
|
// TODO $type can be FQN of a type class
|
2011-03-04 15:01:50 +00:00
|
|
|
|
2011-03-18 11:50:26 +00:00
|
|
|
$builder = 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) {
|
2011-03-18 15:20:00 +00:00
|
|
|
$name = $type;
|
2011-03-02 15:00:31 +00:00
|
|
|
}
|
|
|
|
|
2011-03-18 15:20:00 +00:00
|
|
|
while (null !== $type) {
|
|
|
|
// TODO check if type exists
|
|
|
|
$type = $this->typeLoader->getType($type);
|
|
|
|
array_unshift($hierarchy, $type);
|
|
|
|
$options = array_merge($type->getDefaultOptions($options), $options);
|
|
|
|
$builder = $builder ?: $type->createBuilder($options);
|
|
|
|
$type = $type->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-18 11:50:26 +00:00
|
|
|
$builder->setName($name);
|
|
|
|
$builder->setFormFactory($this);
|
|
|
|
|
2011-03-18 15:20:00 +00:00
|
|
|
foreach ($hierarchy as $type) {
|
|
|
|
$type->configure($builder, $options);
|
2011-02-19 14:26:07 +00:00
|
|
|
}
|
|
|
|
|
2011-03-18 11:50:26 +00:00
|
|
|
return $builder;
|
2011-03-01 14:18:55 +00:00
|
|
|
}
|
2011-03-02 13:58:19 +00:00
|
|
|
|
2011-03-18 15:20:00 +00:00
|
|
|
public function create($type, $name = null, array $options = array())
|
2011-03-18 11:50:26 +00:00
|
|
|
{
|
2011-03-18 15:20:00 +00:00
|
|
|
return $this->createBuilder($type, $name, $options)->getInstance();
|
2011-03-18 11:50:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function createBuilderForProperty($class, $property, array $options = array())
|
2011-03-02 13:58:19 +00:00
|
|
|
{
|
|
|
|
// guess field class and options
|
2011-03-18 15:20:00 +00:00
|
|
|
$typeGuess = $this->guess(function ($guesser) use ($class, $property) {
|
|
|
|
return $guesser->guessType($class, $property);
|
2011-03-02 13:58:19 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// 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
|
2011-03-18 15:20:00 +00:00
|
|
|
$type = $typeGuess ? $typeGuess->getType() : 'text';
|
2011-03-02 13:58:19 +00:00
|
|
|
|
2011-03-18 13:37:54 +00:00
|
|
|
if ($maxLengthGuess) {
|
|
|
|
$options = array_merge(array('max_length' => $maxLengthGuess->getValue()), $options);
|
2011-03-02 13:58:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ($requiredGuess) {
|
|
|
|
$options = array_merge(array('required' => $requiredGuess->getValue()), $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
// user options may override guessed options
|
2011-03-18 15:20:00 +00:00
|
|
|
if ($typeGuess) {
|
|
|
|
$options = array_merge($typeGuess->getOptions(), $options);
|
2011-03-18 13:37:54 +00:00
|
|
|
}
|
2011-03-02 13:58:19 +00:00
|
|
|
|
2011-03-18 15:20:00 +00:00
|
|
|
return $this->createBuilder($type, $property, $options);
|
2011-03-18 11:50:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritDoc
|
|
|
|
*/
|
2011-03-18 13:37:54 +00:00
|
|
|
public function createForProperty($class, $property, array $options = array())
|
2011-03-18 11:50:26 +00:00
|
|
|
{
|
|
|
|
return $this->createBuilderForProperty($class, $property, $options)->getInstance();
|
2011-03-02 13:58:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
}
|