This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/Form/FormFactory.php

157 lines
4.9 KiB
PHP
Raw Normal View History

<?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;
use Symfony\Component\Form\Type\FormTypeInterface;
use Symfony\Component\Form\Type\Loader\TypeLoaderInterface;
use Symfony\Component\Form\Type\Guesser\TypeGuesserInterface;
use Symfony\Component\Form\Type\Guesser\Guess;
use Symfony\Component\Form\Exception\FormException;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
class FormFactory implements FormFactoryInterface
{
private $typeLoader;
private $guessers = array();
public function __construct(TypeLoaderInterface $typeLoader, array $guessers = array())
{
foreach ($guessers as $guesser) {
if (!$guesser instanceof TypeGuesserInterface) {
throw new UnexpectedTypeException($guesser, 'Symfony\Component\Form\Type\Guesser\TypeGuesserInterface');
}
}
$this->typeLoader = $typeLoader;
$this->guessers = $guessers;
}
public function createBuilder($type, $name = null, array $options = array())
{
// TODO $type can be FQN of a type class
2011-03-04 15:01:50 +00:00
$builder = null;
$types = array();
$knownOptions = array();
$passedOptions = array_keys($options);
// TESTME
if (null === $name) {
$name = is_object($type) ? $type->getName() : $type;
}
while (null !== $type) {
// TODO check if type exists
if (!$type instanceof FormTypeInterface) {
$type = $this->typeLoader->getType($type);
}
array_unshift($types, $type);
$defaultOptions = $type->getDefaultOptions($options);
$options = array_merge($defaultOptions, $options);
$knownOptions = array_merge($knownOptions, array_keys($defaultOptions));
$type = $type->getParent($options);
}
$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) {
$builder = $types[$i]->createBuilder($name, $this, $options);
}
// TODO check if instance exists
$builder->setTypes($types);
foreach ($types as $type) {
$type->buildForm($builder, $options);
}
return $builder;
}
public function create($type, $name = null, array $options = array())
{
return $this->createBuilder($type, $name, $options)->getForm();
}
public function createBuilderForProperty($class, $property, array $options = array())
{
// guess field class and options
$typeGuess = $this->guess(function ($guesser) use ($class, $property) {
return $guesser->guessType($class, $property);
});
// 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
$type = $typeGuess ? $typeGuess->getType() : 'text';
if ($maxLengthGuess) {
$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
if ($typeGuess) {
$options = array_merge($typeGuess->getOptions(), $options);
}
return $this->createBuilder($type, $property, $options);
}
/**
* @inheritDoc
*/
public function createForProperty($class, $property, array $options = array())
{
return $this->createBuilderForProperty($class, $property, $options)->getForm();
}
/**
* 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 Guess::getBestGuess($guesses);
}
}