2011-02-19 12:52:37 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is part of the Symfony package.
|
|
|
|
*
|
2011-04-24 12:59:46 +01:00
|
|
|
* (c) Fabien Potencier <fabien@symfony.com>
|
2011-02-19 12:52:37 +00:00
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace Symfony\Component\Form;
|
|
|
|
|
2011-04-22 16:41:21 +01:00
|
|
|
use Symfony\Component\Form\Guess\Guess;
|
2011-03-25 14:30:33 +00:00
|
|
|
use Symfony\Component\Form\Exception\FormException;
|
2011-04-24 20:56:06 +01:00
|
|
|
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
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-04-22 16:41:21 +01:00
|
|
|
private $extensions = array();
|
2011-03-02 13:58:19 +00:00
|
|
|
|
2011-04-22 18:22:26 +01:00
|
|
|
private $types = array();
|
|
|
|
|
2011-04-22 16:41:21 +01:00
|
|
|
private $guesser;
|
2011-03-02 13:58:19 +00:00
|
|
|
|
2011-04-24 20:56:06 +01:00
|
|
|
public function __construct(array $extensions)
|
2011-02-19 12:52:37 +00:00
|
|
|
{
|
2011-04-22 16:41:21 +01:00
|
|
|
foreach ($extensions as $extension) {
|
2011-04-24 20:56:06 +01:00
|
|
|
if (!$extension instanceof FormExtensionInterface) {
|
|
|
|
throw new UnexpectedTypeException($extension, 'Symfony\Component\Form\FormExtensionInterface');
|
|
|
|
}
|
2011-03-25 01:26:14 +00:00
|
|
|
}
|
2011-04-22 16:41:21 +01:00
|
|
|
|
2011-04-24 20:56:06 +01:00
|
|
|
$this->extensions = $extensions;
|
2011-04-22 16:41:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private function loadGuesser()
|
|
|
|
{
|
|
|
|
$guessers = array();
|
|
|
|
|
|
|
|
foreach ($this->extensions as $extension) {
|
|
|
|
$guesser = $extension->getTypeGuesser();
|
|
|
|
|
|
|
|
if ($guesser) {
|
|
|
|
$guessers[] = $guesser;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->guesser = new FormTypeGuesserChain($guessers);
|
2011-02-19 12:52:37 +00:00
|
|
|
}
|
|
|
|
|
2011-04-22 18:22:26 +01:00
|
|
|
public function getType($name)
|
|
|
|
{
|
|
|
|
$type = null;
|
|
|
|
|
|
|
|
if ($name instanceof FormTypeInterface) {
|
|
|
|
$type = $name;
|
|
|
|
$name = $type->getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isset($this->types[$name])) {
|
|
|
|
if (!$type) {
|
|
|
|
foreach ($this->extensions as $extension) {
|
|
|
|
if ($extension->hasType($name)) {
|
|
|
|
$type = $extension->getType($name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$type) {
|
|
|
|
throw new FormException(sprintf('Could not load type "%s"', $name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$typeExtensions = array();
|
|
|
|
|
|
|
|
foreach ($this->extensions as $extension) {
|
|
|
|
$typeExtensions = array_merge(
|
|
|
|
$typeExtensions,
|
|
|
|
$extension->getTypeExtensions($name)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$type->setExtensions($typeExtensions);
|
|
|
|
|
|
|
|
$this->types[$name] = $type;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->types[$name];
|
|
|
|
}
|
|
|
|
|
2011-04-22 09:42:21 +01:00
|
|
|
public function create($type, $data = null, array $options = array())
|
2011-02-19 14:26:07 +00:00
|
|
|
{
|
2011-04-22 09:42:21 +01:00
|
|
|
return $this->createBuilder($type, $data, $options)->getForm();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function createNamed($type, $name, $data = null, array $options = array())
|
|
|
|
{
|
|
|
|
return $this->createNamedBuilder($type, $name, $data, $options)->getForm();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @inheritDoc
|
|
|
|
*/
|
|
|
|
public function createForProperty($class, $property, $data = null, array $options = array())
|
|
|
|
{
|
|
|
|
return $this->createBuilderForProperty($class, $property, $data, $options)->getForm();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function createBuilder($type, $data = null, array $options = array())
|
|
|
|
{
|
|
|
|
$name = is_object($type) ? $type->getName() : $type;
|
|
|
|
|
|
|
|
return $this->createNamedBuilder($type, $name, $data, $options);
|
|
|
|
}
|
2011-03-04 15:01:50 +00:00
|
|
|
|
2011-04-22 09:42:21 +01:00
|
|
|
public function createNamedBuilder($type, $name, $data = null, array $options = array())
|
|
|
|
{
|
2011-03-18 11:50:26 +00:00
|
|
|
$builder = null;
|
2011-03-24 15:16:31 +00:00
|
|
|
$types = array();
|
2011-03-25 14:30:33 +00:00
|
|
|
$knownOptions = array();
|
|
|
|
$passedOptions = array_keys($options);
|
2011-02-21 22:40:12 +00:00
|
|
|
|
2011-04-24 12:32:29 +01:00
|
|
|
if (!array_key_exists('data', $options)) {
|
|
|
|
$options['data'] = $data;
|
|
|
|
}
|
|
|
|
|
2011-03-18 15:20:00 +00:00
|
|
|
while (null !== $type) {
|
2011-04-22 18:22:26 +01:00
|
|
|
$type = $this->getType($type);
|
2011-04-22 16:41:21 +01:00
|
|
|
|
2011-04-22 18:22:26 +01:00
|
|
|
$defaultOptions = $type->getDefaultOptions($options);
|
|
|
|
|
|
|
|
foreach ($type->getExtensions() as $typeExtension) {
|
|
|
|
$defaultOptions = array_merge($defaultOptions, $typeExtension->getDefaultOptions($options));
|
2011-03-26 17:48:55 +00:00
|
|
|
}
|
|
|
|
|
2011-03-25 14:30:33 +00:00
|
|
|
$options = array_merge($defaultOptions, $options);
|
|
|
|
$knownOptions = array_merge($knownOptions, array_keys($defaultOptions));
|
2011-04-22 18:22:26 +01:00
|
|
|
array_unshift($types, $type);
|
2011-03-18 15:20:00 +00:00
|
|
|
$type = $type->getParent($options);
|
2011-02-21 22:40:12 +00:00
|
|
|
}
|
2011-02-19 12:52:37 +00:00
|
|
|
|
2011-03-25 14:30:33 +00:00
|
|
|
$diff = array_diff($passedOptions, $knownOptions);
|
|
|
|
|
|
|
|
if (count($diff) > 0) {
|
|
|
|
throw new FormException(sprintf('The options "%s" do not exist', implode('", "', $diff)));
|
|
|
|
}
|
|
|
|
|
|
|
|
for ($i = 0, $l = count($types); $i < $l && !$builder; ++$i) {
|
2011-04-14 14:25:30 +01:00
|
|
|
$builder = $types[$i]->createBuilder($name, $this, $options);
|
2011-03-25 14:30:33 +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-24 15:16:31 +00:00
|
|
|
$builder->setTypes($types);
|
2011-03-18 11:50:26 +00:00
|
|
|
|
2011-03-24 15:16:31 +00:00
|
|
|
foreach ($types as $type) {
|
2011-03-26 17:52:24 +00:00
|
|
|
$type->buildForm($builder, $options);
|
2011-04-22 18:22:26 +01:00
|
|
|
|
|
|
|
foreach ($type->getExtensions() as $typeExtension) {
|
|
|
|
$typeExtension->buildForm($builder, $options);
|
|
|
|
}
|
2011-02-19 14:26:07 +00:00
|
|
|
}
|
|
|
|
|
2011-04-22 09:42:21 +01:00
|
|
|
return $builder;
|
2011-03-18 11:50:26 +00:00
|
|
|
}
|
|
|
|
|
2011-04-22 09:42:21 +01:00
|
|
|
public function createBuilderForProperty($class, $property, $data = null, array $options = array())
|
2011-03-02 13:58:19 +00:00
|
|
|
{
|
2011-04-22 16:41:21 +01:00
|
|
|
if (!$this->guesser) {
|
|
|
|
$this->loadGuesser();
|
|
|
|
}
|
|
|
|
|
|
|
|
$typeGuess = $this->guesser->guessType($class, $property);
|
|
|
|
$maxLengthGuess = $this->guesser->guessMaxLength($class, $property);
|
|
|
|
$requiredGuess = $this->guesser->guessRequired($class, $property);
|
|
|
|
|
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-04-22 09:42:21 +01:00
|
|
|
return $this->createNamedBuilder($type, $property, $data, $options);
|
2011-03-02 13:58:19 +00:00
|
|
|
}
|
2011-03-24 21:20:54 +00:00
|
|
|
}
|