4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\Form
;
14 use Symfony\Component\Form\Exception\BadMethodCallException
;
15 use Symfony\Component\Form\Exception\InvalidArgumentException
;
16 use Symfony\Component\Form\Exception\UnexpectedTypeException
;
17 use Symfony\Component\PropertyAccess\PropertyPath
;
18 use Symfony\Component\PropertyAccess\PropertyPathInterface
;
19 use Symfony\Component\EventDispatcher\EventDispatcherInterface
;
20 use Symfony\Component\EventDispatcher\EventSubscriberInterface
;
21 use Symfony\Component\EventDispatcher\ImmutableEventDispatcher
;
24 * A basic form configuration.
26 * @author Bernhard Schussek <bschussek@gmail.com>
28 class FormConfigBuilder
implements FormConfigBuilderInterface
31 * Caches a globally unique {@link NativeRequestHandler} instance.
33 * @var NativeRequestHandler
35 private static $nativeRequestProcessor;
38 * The accepted request methods.
42 private static $allowedMethods = array(
53 protected $locked = false;
56 * @var EventDispatcherInterface
66 * @var PropertyPathInterface
68 private $propertyPath;
73 private $mapped = true;
78 private $byReference = true;
83 private $inheritData = false;
88 private $compound = false;
91 * @var ResolvedFormTypeInterface
98 private $viewTransformers = array();
103 private $modelTransformers = array();
106 * @var DataMapperInterface
113 private $required = true;
118 private $disabled = false;
123 private $errorBubbling = false;
133 private $attributes = array();
151 * @var FormFactoryInterface
153 private $formFactory;
163 private $method = 'POST';
166 * @var RequestHandlerInterface
168 private $requestHandler;
173 private $autoInitialize = false;
181 * Creates an empty form configuration.
183 * @param string|integer $name The form name
184 * @param string $dataClass The class of the form's data
185 * @param EventDispatcherInterface $dispatcher The event dispatcher
186 * @param array $options The form options
188 * @throws InvalidArgumentException If the data class is not a valid class or if
189 * the name contains invalid characters.
191 public function __construct($name, $dataClass, EventDispatcherInterface
$dispatcher, array $options = array())
193 self
::validateName($name);
195 if (null !== $dataClass && !class_exists($dataClass)) {
196 throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass));
199 $this->name
= (string) $name;
200 $this->dataClass
= $dataClass;
201 $this->dispatcher
= $dispatcher;
202 $this->options
= $options;
208 public function addEventListener($eventName, $listener, $priority = 0)
211 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
214 $this->dispatcher
->addListener($eventName, $listener, $priority);
222 public function addEventSubscriber(EventSubscriberInterface
$subscriber)
225 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
228 $this->dispatcher
->addSubscriber($subscriber);
236 public function addViewTransformer(DataTransformerInterface
$viewTransformer, $forcePrepend = false)
239 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
243 array_unshift($this->viewTransformers
, $viewTransformer);
245 $this->viewTransformers
[] = $viewTransformer;
254 public function resetViewTransformers()
257 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
260 $this->viewTransformers
= array();
268 public function addModelTransformer(DataTransformerInterface
$modelTransformer, $forceAppend = false)
271 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
275 $this->modelTransformers
[] = $modelTransformer;
277 array_unshift($this->modelTransformers
, $modelTransformer);
286 public function resetModelTransformers()
289 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
292 $this->modelTransformers
= array();
300 public function getEventDispatcher()
302 if ($this->locked
&& !$this->dispatcher
instanceof ImmutableEventDispatcher
) {
303 $this->dispatcher
= new ImmutableEventDispatcher($this->dispatcher
);
306 return $this->dispatcher
;
312 public function getName()
320 public function getPropertyPath()
322 return $this->propertyPath
;
328 public function getMapped()
330 return $this->mapped
;
336 public function getByReference()
338 return $this->byReference
;
344 public function getInheritData()
346 return $this->inheritData
;
350 * Alias of {@link getInheritData()}.
352 * @return FormConfigBuilder The configuration object.
354 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
355 * {@link getInheritData()} instead.
357 public function getVirtual()
359 // Uncomment this as soon as the deprecation note should be shown
360 // trigger_error('getVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use getInheritData() instead.', E_USER_DEPRECATED);
361 return $this->getInheritData();
367 public function getCompound()
369 return $this->compound
;
375 public function getType()
383 public function getViewTransformers()
385 return $this->viewTransformers
;
391 public function getModelTransformers()
393 return $this->modelTransformers
;
399 public function getDataMapper()
401 return $this->dataMapper
;
407 public function getRequired()
409 return $this->required
;
415 public function getDisabled()
417 return $this->disabled
;
423 public function getErrorBubbling()
425 return $this->errorBubbling
;
431 public function getEmptyData()
433 return $this->emptyData
;
439 public function getAttributes()
441 return $this->attributes
;
447 public function hasAttribute($name)
449 return array_key_exists($name, $this->attributes
);
455 public function getAttribute($name, $default = null)
457 return array_key_exists($name, $this->attributes
) ? $this->attributes
[$name] : $default;
463 public function getData()
471 public function getDataClass()
473 return $this->dataClass
;
479 public function getDataLocked()
481 return $this->dataLocked
;
487 public function getFormFactory()
489 return $this->formFactory
;
495 public function getAction()
497 return $this->action
;
503 public function getMethod()
505 return $this->method
;
511 public function getRequestHandler()
513 if (null === $this->requestHandler
) {
514 if (null === self
::$nativeRequestProcessor) {
515 self
::$nativeRequestProcessor = new NativeRequestHandler();
517 $this->requestHandler
= self
::$nativeRequestProcessor;
520 return $this->requestHandler
;
526 public function getAutoInitialize()
528 return $this->autoInitialize
;
534 public function getOptions()
536 return $this->options
;
542 public function hasOption($name)
544 return array_key_exists($name, $this->options
);
550 public function getOption($name, $default = null)
552 return array_key_exists($name, $this->options
) ? $this->options
[$name] : $default;
558 public function setAttribute($name, $value)
561 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
564 $this->attributes
[$name] = $value;
572 public function setAttributes(array $attributes)
575 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
578 $this->attributes
= $attributes;
586 public function setDataMapper(DataMapperInterface
$dataMapper = null)
589 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
592 $this->dataMapper
= $dataMapper;
600 public function setDisabled($disabled)
603 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
606 $this->disabled
= (Boolean
) $disabled;
614 public function setEmptyData($emptyData)
617 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
620 $this->emptyData
= $emptyData;
628 public function setErrorBubbling($errorBubbling)
631 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
634 $this->errorBubbling
= null === $errorBubbling ? null : (Boolean
) $errorBubbling;
642 public function setRequired($required)
645 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
648 $this->required
= (Boolean
) $required;
656 public function setPropertyPath($propertyPath)
659 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
662 if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface
) {
663 $propertyPath = new PropertyPath($propertyPath);
666 $this->propertyPath
= $propertyPath;
674 public function setMapped($mapped)
677 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
680 $this->mapped
= $mapped;
688 public function setByReference($byReference)
691 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
694 $this->byReference
= $byReference;
702 public function setInheritData($inheritData)
705 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
708 $this->inheritData
= $inheritData;
714 * Alias of {@link setInheritData()}.
716 * @param Boolean $inheritData Whether the form should inherit its parent's data.
718 * @return FormConfigBuilder The configuration object.
720 * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use
721 * {@link setInheritData()} instead.
723 public function setVirtual($inheritData)
725 // Uncomment this as soon as the deprecation note should be shown
726 // trigger_error('setVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use setInheritData() instead.', E_USER_DEPRECATED);
728 $this->setInheritData($inheritData);
734 public function setCompound($compound)
737 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
740 $this->compound
= $compound;
748 public function setType(ResolvedFormTypeInterface
$type)
751 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
762 public function setData($data)
765 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
776 public function setDataLocked($locked)
779 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
782 $this->dataLocked
= $locked;
790 public function setFormFactory(FormFactoryInterface
$formFactory)
793 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
796 $this->formFactory
= $formFactory;
804 public function setAction($action)
807 throw new BadMethodCallException('The config builder cannot be modified anymore.');
810 $this->action
= $action;
818 public function setMethod($method)
821 throw new BadMethodCallException('The config builder cannot be modified anymore.');
824 $upperCaseMethod = strtoupper($method);
826 if (!in_array($upperCaseMethod, self
::$allowedMethods)) {
827 throw new InvalidArgumentException(sprintf(
828 'The form method is "%s", but should be one of "%s".',
830 implode('", "', self
::$allowedMethods)
834 $this->method
= $upperCaseMethod;
842 public function setRequestHandler(RequestHandlerInterface
$requestHandler)
845 throw new BadMethodCallException('The config builder cannot be modified anymore.');
848 $this->requestHandler
= $requestHandler;
856 public function setAutoInitialize($initialize)
858 $this->autoInitialize
= (Boolean
) $initialize;
866 public function getFormConfig()
869 throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.');
872 // This method should be idempotent, so clone the builder
873 $config = clone $this;
874 $config->locked
= true;
880 * Validates whether the given variable is a valid form name.
882 * @param string|integer $name The tested form name.
884 * @throws UnexpectedTypeException If the name is not a string or an integer.
885 * @throws InvalidArgumentException If the name contains invalid characters.
887 public static function validateName($name)
889 if (null !== $name && !is_string($name) && !is_int($name)) {
890 throw new UnexpectedTypeException($name, 'string, integer or null');
893 if (!self
::isValidName($name)) {
894 throw new InvalidArgumentException(sprintf(
895 'The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").',
902 * Returns whether the given variable contains a valid form name.
904 * A name is accepted if it
907 * * starts with a letter, digit or underscore
908 * * contains only letters, digits, numbers, underscores ("_"),
909 * hyphens ("-") and colons (":")
911 * @param string $name The tested form name.
913 * @return Boolean Whether the name is valid.
915 public static function isValidName($name)
917 return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name);