From 796991bf9d2a5d2f8ab76f6ef157483400077b7e Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 13 May 2011 18:29:18 +0200 Subject: [PATCH] [Form] Improved test coverage of FormFactory and improved error handling --- Exception/CreationException.php | 21 +++++ Exception/TypeDefinitionException.php | 21 +++++ FormFactory.php | 114 +++++++++++++++++++------- FormFactoryInterface.php | 4 + 4 files changed, 130 insertions(+), 30 deletions(-) create mode 100644 Exception/CreationException.php create mode 100644 Exception/TypeDefinitionException.php diff --git a/Exception/CreationException.php b/Exception/CreationException.php new file mode 100644 index 0000000000..9742103d62 --- /dev/null +++ b/Exception/CreationException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Thrown when a form could not be constructed by a FormFactory + * + * @author Bernhard Schussek + */ +class CreationException extends FormException +{ +} \ No newline at end of file diff --git a/Exception/TypeDefinitionException.php b/Exception/TypeDefinitionException.php new file mode 100644 index 0000000000..9c88d4a6e7 --- /dev/null +++ b/Exception/TypeDefinitionException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Thrown when a form type is configured incorrectly + * + * @author Bernhard Schussek + */ +class TypeDefinitionException extends FormException +{ +} \ No newline at end of file diff --git a/FormFactory.php b/FormFactory.php index bd103ff5df..365482941d 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -13,9 +13,17 @@ use Symfony\Component\Form\Exception\FormException; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Exception\TypeDefinitionException; +use Symfony\Component\Form\Exception\CreationException; class FormFactory implements FormFactoryInterface { + private static $requiredOptions = array( + 'data', + 'required', + 'max_length', + ); + private $extensions = array(); private $types = array(); @@ -40,41 +48,36 @@ public function __construct(array $extensions) $this->extensions = $extensions; } - public function getType($name) + public function hasType($name) { - $type = null; + if (isset($this->types[$name])) { + return true; + } - if ($name instanceof FormTypeInterface) { - $type = $name; - $name = $type->getName(); + try { + $this->loadType($name); + } catch (FormException $e) { + return false; } - 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)); - } - } + return true; + } - $typeExtensions = array(); + public function addType(FormTypeInterface $type) + { + $this->loadTypeExtensions($type); - foreach ($this->extensions as $extension) { - $typeExtensions = array_merge( - $typeExtensions, - $extension->getTypeExtensions($name) - ); - } + $this->types[$type->getName()] = $type; + } - $type->setExtensions($typeExtensions); + public function getType($name) + { + if (!is_string($name)) { + throw new UnexpectedTypeException($name, 'string'); + } - $this->types[$name] = $type; + if (!isset($this->types[$name])) { + $this->loadType($name); } return $this->types[$name]; @@ -117,7 +120,11 @@ public function createNamedBuilder($type, $name, $data = null, array $options = } while (null !== $type) { - $type = $this->getType($type); + if ($type instanceof FormTypeInterface) { + $this->addType($type); + } else { + $type = $this->getType($type); + } $defaultOptions = $type->getDefaultOptions($options); @@ -131,17 +138,30 @@ public function createNamedBuilder($type, $name, $data = null, array $options = $type = $type->getParent($options); } + $type = end($types); + $diff = array_diff(self::$requiredOptions, $knownOptions); + + if (count($diff) > 0) { + throw new TypeDefinitionException(sprintf('Type "%s" should support the option(s) "%s"', $type->getName(), implode('", "', $diff))); + } + $diff = array_diff($passedOptions, $knownOptions); + if (count($diff) > 1) { + throw new CreationException(sprintf('The options "%s" do not exist', implode('", "', $diff))); + } + if (count($diff) > 0) { - throw new FormException(sprintf('The options "%s" do not exist', implode('", "', $diff))); + throw new CreationException(sprintf('The option "%s" does not exist', $diff[0])); } for ($i = 0, $l = count($types); $i < $l && !$builder; ++$i) { $builder = $types[$i]->createBuilder($name, $this, $options); } - // TODO check if instance exists + if (!$builder) { + throw new TypeDefinitionException(sprintf('Type "%s" or any of its parents should return a FormBuilder instance from createBuilder()', $type->getName())); + } $builder->setTypes($types); @@ -198,4 +218,38 @@ private function loadGuesser() $this->guesser = new FormTypeGuesserChain($guessers); } + + private function loadType($name) + { + $type = null; + + 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)); + } + + $this->loadTypeExtensions($type); + + $this->types[$name] = $type; + } + + private function loadTypeExtensions(FormTypeInterface $type) + { + $typeExtensions = array(); + + foreach ($this->extensions as $extension) { + $typeExtensions = array_merge( + $typeExtensions, + $extension->getTypeExtensions($type->getName()) + ); + } + + $type->setExtensions($typeExtensions); + } } diff --git a/FormFactoryInterface.php b/FormFactoryInterface.php index 0418de5145..6206737cc0 100644 --- a/FormFactoryInterface.php +++ b/FormFactoryInterface.php @@ -26,4 +26,8 @@ function createNamedBuilder($type, $name, $data = null, array $options = array() function createBuilderForProperty($class, $property, $data = null, array $options = array()); function getType($name); + + function hasType($name); + + function addType(FormTypeInterface $type); }