2011-03-18 15:34:54 +00:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . 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-19 13:31:25 +00:00
use Symfony\Component\Form\Exception\FormException ;
2011-03-19 18:20:55 +00:00
use Symfony\Component\Form\Exception\UnexpectedTypeException ;
2011-03-18 15:34:54 +00:00
use Symfony\Component\EventDispatcher\EventDispatcherInterface ;
2011-03-20 12:35:19 +00:00
use Symfony\Component\EventDispatcher\EventSubscriberInterface ;
2011-03-18 15:34:54 +00:00
2011-03-20 12:35:19 +00:00
class FormBuilder
2011-03-18 15:34:54 +00:00
{
2011-05-10 13:24:23 +01:00
/**
* @ var string
*/
2011-03-20 12:35:19 +00:00
private $name ;
2011-05-10 13:24:23 +01:00
/**
* The form data in application format
* @ var mixed
*/
private $appData ;
2011-03-20 12:35:19 +00:00
2011-05-10 13:24:23 +01:00
/**
* The event dispatcher
*
* @ var EventDispatcherInterface
*/
2011-03-20 12:35:19 +00:00
private $dispatcher ;
2011-05-10 13:24:23 +01:00
/**
* The form factory
* @ var FormFactoryInterface
*/
2011-03-20 12:35:19 +00:00
private $factory ;
2011-05-10 13:24:23 +01:00
/**
* @ var Boolean
*/
2011-03-20 12:35:19 +00:00
private $readOnly ;
2011-05-10 13:24:23 +01:00
/**
* @ var Boolean
*/
2011-03-20 12:35:19 +00:00
private $required ;
2011-05-10 13:24:23 +01:00
/**
* The transformers for transforming from normalized to client format and
* back
* @ var array An array of DataTransformerInterface
*/
2011-04-02 15:39:19 +01:00
private $clientTransformers = array ();
2011-03-20 12:35:19 +00:00
2011-05-10 13:24:23 +01:00
/**
* The transformers for transforming from application to normalized format
* and back
* @ var array An array of DataTransformerInterface
*/
2011-04-02 15:39:19 +01:00
private $normTransformers = array ();
2011-03-20 12:35:19 +00:00
2011-05-10 13:24:23 +01:00
/**
* @ var array An array of FormValidatorInterface
*/
2011-03-20 12:35:19 +00:00
private $validators = array ();
2011-05-10 13:24:23 +01:00
/**
* Key - value store for arbitrary attributes attached to the form
* @ var array
*/
2011-03-20 12:35:19 +00:00
private $attributes = array ();
2011-05-10 13:24:23 +01:00
/**
* @ var array An array of FormTypeInterface
*/
2011-03-24 15:16:31 +00:00
private $types = array ();
2011-05-10 13:24:23 +01:00
/**
* @ var string
*/
2011-03-18 15:34:54 +00:00
private $dataClass ;
2011-05-10 13:24:23 +01:00
/**
* The children of the form
* @ var array
*/
2011-03-25 01:12:01 +00:00
private $children = array ();
2011-03-18 15:34:54 +00:00
2011-05-10 13:24:23 +01:00
/**
* @ var DataMapperInterface
*/
2011-03-18 15:34:54 +00:00
private $dataMapper ;
2011-05-10 13:24:23 +01:00
/**
* Whether added errors should bubble up to the parent
* @ var Boolean
*/
2011-03-21 21:10:53 +00:00
private $errorBubbling = false ;
2011-05-10 13:24:23 +01:00
/**
* Data used for the client data when no value is bound
* @ var mixed
*/
2011-04-06 12:45:19 +01:00
private $emptyData = '' ;
2011-03-27 14:12:35 +01:00
2011-05-10 13:24:23 +01:00
/**
* Constructor .
*
* @ param string $name
* @ param FormFactoryInterface $factory
* @ param EventDispatcherInterface $dispatcher
* @ param string $dataClass
*/
2011-04-14 14:25:30 +01:00
public function __construct ( $name , FormFactoryInterface $factory , EventDispatcherInterface $dispatcher , $dataClass = null )
2011-03-20 12:35:19 +00:00
{
2011-03-31 12:48:06 +01:00
$this -> name = $name ;
2011-04-14 14:25:30 +01:00
$this -> factory = $factory ;
2011-03-20 12:35:19 +00:00
$this -> dispatcher = $dispatcher ;
2011-03-27 13:34:48 +01:00
$this -> dataClass = $dataClass ;
2011-03-20 12:35:19 +00:00
}
2011-05-10 13:24:23 +01:00
/**
* Returns the associated form factory .
*
* @ return FormFactoryInterface The factory
*/
2011-03-20 12:35:19 +00:00
public function getFormFactory ()
{
return $this -> factory ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns the name of the form .
*
* @ return string The form name
*/
2011-03-20 12:35:19 +00:00
public function getName ()
{
return $this -> name ;
}
2011-05-10 13:24:23 +01:00
/**
* Updates the field with default data .
*
* @ param array $appData The data formatted as expected for the underlying object
*
* @ return FormBuilder The current builder
*/
public function setData ( $appData )
2011-03-20 12:35:19 +00:00
{
2011-05-10 13:24:23 +01:00
$this -> appData = $appData ;
2011-03-20 12:35:19 +00:00
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns the data in the format needed for the underlying object .
*
* @ return mixed
*/
2011-03-20 12:35:19 +00:00
public function getData ()
{
2011-05-10 13:24:23 +01:00
return $this -> appData ;
2011-03-20 12:35:19 +00:00
}
2011-05-10 13:24:23 +01:00
/**
* Set whether the form is read only
*
* @ param Boolean $readOnly Whether the form is read only
*
* @ return FormBuilder The current builder
*/
2011-03-20 12:35:19 +00:00
public function setReadOnly ( $readOnly )
{
2011-05-10 13:24:23 +01:00
$this -> readOnly = ( Boolean ) $readOnly ;
2011-03-20 12:35:19 +00:00
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns whether the form is read only .
*
* @ return Boolean Whether the form is read only
*/
2011-03-20 12:35:19 +00:00
public function getReadOnly ()
{
return $this -> readOnly ;
}
/**
* Sets whether this field is required to be filled out when bound .
*
* @ param Boolean $required
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-03-20 12:35:19 +00:00
*/
public function setRequired ( $required )
{
2011-05-10 13:24:23 +01:00
$this -> required = ( Boolean ) $required ;
2011-03-20 12:35:19 +00:00
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns whether this field is required to be filled out when bound .
*
* @ return Boolean Whether this field is required
*/
2011-03-20 12:35:19 +00:00
public function getRequired ()
{
return $this -> required ;
}
2011-05-10 13:24:23 +01:00
/**
* Sets whether errors bubble up to the parent .
*
* @ param type $errorBubbling
*
* @ return FormBuilder The current builder
*/
2011-03-21 21:10:53 +00:00
public function setErrorBubbling ( $errorBubbling )
{
2011-05-10 13:24:23 +01:00
$this -> errorBubbling = ( Boolean ) $errorBubbling ;
2011-03-21 21:10:53 +00:00
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns whether errors bubble up to the parent .
*
* @ return Boolean
*/
2011-03-21 21:10:53 +00:00
public function getErrorBubbling ()
{
return $this -> errorBubbling ;
}
2011-05-10 13:24:23 +01:00
/**
* Adds a validator to the form .
*
* @ param FormValidatorInterface $validator The validator
*
* @ return FormBuilder The current builder
*/
2011-03-20 12:35:19 +00:00
public function addValidator ( FormValidatorInterface $validator )
{
$this -> validators [] = $validator ;
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns the validators used by the form .
*
* @ return array An array of FormValidatorInterface
*/
2011-03-20 12:35:19 +00:00
public function getValidators ()
{
return $this -> validators ;
}
/**
* Adds an event listener for events on this field
*
2011-05-30 08:19:21 +01:00
* @ see Symfony\Component\EventDispatcher\EventDispatcherInterface :: addListener
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-03-20 12:35:19 +00:00
*/
2011-05-05 18:02:52 +01:00
public function addEventListener ( $eventName , $listener , $priority = 0 )
2011-03-20 12:35:19 +00:00
{
2011-05-05 18:02:52 +01:00
$this -> dispatcher -> addListener ( $eventName , $listener , $priority );
2011-03-20 12:35:19 +00:00
return $this ;
}
/**
* Adds an event subscriber for events on this field
*
2011-05-30 08:19:21 +01:00
* @ see Symfony\Component\EventDispatcher\EventDispatcherInterface :: addSubscriber
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-03-20 12:35:19 +00:00
*/
public function addEventSubscriber ( EventSubscriberInterface $subscriber , $priority = 0 )
{
$this -> dispatcher -> addSubscriber ( $subscriber , $priority );
return $this ;
}
2011-04-02 15:39:19 +01:00
/**
* Appends a transformer to the normalization transformer chain
*
* @ param DataTransformerInterface $clientTransformer
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-04-02 15:39:19 +01:00
*/
2011-05-10 13:25:34 +01:00
public function appendNormTransformer ( DataTransformerInterface $normTransformer )
2011-03-20 12:35:19 +00:00
{
2011-04-02 15:39:19 +01:00
$this -> normTransformers [] = $normTransformer ;
return $this ;
2011-03-20 12:35:19 +00:00
}
/**
2011-04-02 15:39:19 +01:00
* Prepends a transformer to the client transformer chain
2011-03-20 12:35:19 +00:00
*
2011-04-23 16:05:44 +01:00
* @ param DataTransformerInterface $normTransformer
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-03-20 12:35:19 +00:00
*/
2011-05-10 13:24:23 +01:00
public function prependNormTransformer ( DataTransformerInterface $normTransformer )
2011-03-20 12:35:19 +00:00
{
2011-04-02 15:39:19 +01:00
array_unshift ( $this -> normTransformers , $normTransformer );
2011-03-20 12:35:19 +00:00
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Clears the normalization transformers .
*
* @ return FormBuilder The current builder
*/
2011-04-02 15:39:19 +01:00
public function resetNormTransformers ()
{
$this -> normTransformers = array ();
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns all the normalization transformers .
*
* @ return array An array of DataTransformerInterface
*/
2011-04-02 15:39:19 +01:00
public function getNormTransformers ()
{
return $this -> normTransformers ;
}
/**
* Appends a transformer to the client transformer chain
*
* @ param DataTransformerInterface $clientTransformer
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-04-02 15:39:19 +01:00
*/
2011-05-10 13:25:34 +01:00
public function appendClientTransformer ( DataTransformerInterface $clientTransformer )
2011-03-20 12:35:19 +00:00
{
2011-04-02 15:39:19 +01:00
$this -> clientTransformers [] = $clientTransformer ;
return $this ;
2011-03-20 12:35:19 +00:00
}
/**
2011-04-02 15:39:19 +01:00
* Prepends a transformer to the client transformer chain
2011-03-20 12:35:19 +00:00
*
* @ param DataTransformerInterface $clientTransformer
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-03-20 12:35:19 +00:00
*/
2011-05-10 13:25:34 +01:00
public function prependClientTransformer ( DataTransformerInterface $clientTransformer )
2011-03-20 12:35:19 +00:00
{
2011-04-02 15:39:19 +01:00
array_unshift ( $this -> clientTransformers , $clientTransformer );
2011-03-20 12:35:19 +00:00
return $this ;
}
2011-05-10 13:26:38 +01:00
/**
* Clears the client transformers .
*
* @ return FormBuilder The current builder
*/
2011-04-02 15:39:19 +01:00
public function resetClientTransformers ()
2011-03-20 12:35:19 +00:00
{
2011-04-02 15:39:19 +01:00
$this -> clientTransformers = array ();
2011-05-10 13:26:38 +01:00
return $this ;
2011-04-02 15:39:19 +01:00
}
2011-05-10 13:24:23 +01:00
/**
* Returns all the client transformers .
*
* @ return array An array of DataTransformerInterface
*/
2011-04-02 15:39:19 +01:00
public function getClientTransformers ()
{
return $this -> clientTransformers ;
2011-03-20 12:35:19 +00:00
}
2011-05-10 13:24:23 +01:00
/**
* Sets the value for an attribute .
*
* @ param string $name The name of the attribute
* @ param string $value The value of the attribute
*
* @ return FormBuilder The current builder
*/
2011-03-20 12:35:19 +00:00
public function setAttribute ( $name , $value )
{
$this -> attributes [ $name ] = $value ;
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns the value of the attributes with the given name .
*
* @ param string $name The name of the attribute
*/
2011-03-20 12:35:19 +00:00
public function getAttribute ( $name )
{
return $this -> attributes [ $name ];
}
2011-05-10 13:24:23 +01:00
/**
* Returns whether the form has an attribute with the given name .
*
* @ param string $name The name of the attribute
*/
2011-03-20 12:35:19 +00:00
public function hasAttribute ( $name )
{
return isset ( $this -> attributes [ $name ]);
}
2011-05-10 13:24:23 +01:00
/**
* Returns all the attributes .
*
* @ return array An array of attributes
*/
2011-03-20 12:35:19 +00:00
public function getAttributes ()
{
return $this -> attributes ;
}
2011-05-10 13:24:23 +01:00
/**
* Sets the data mapper used by the form .
*
* @ param DataMapperInterface $dataMapper
*
* @ return FormBuilder The current builder
*/
2011-03-18 15:34:54 +00:00
public function setDataMapper ( DataMapperInterface $dataMapper )
{
$this -> dataMapper = $dataMapper ;
2011-04-02 10:22:29 +01:00
return $this ;
2011-03-18 15:34:54 +00:00
}
2011-05-10 13:24:23 +01:00
/**
* Returns the data mapper used by the form .
*
* @ return array An array of DataMapperInterface
*/
2011-03-18 15:34:54 +00:00
public function getDataMapper ()
{
return $this -> dataMapper ;
}
2011-05-10 13:24:23 +01:00
/**
* Set the types .
*
* @ param array $types An array FormTypeInterface
*
* @ return FormBuilder The current builder
*/
2011-03-24 15:16:31 +00:00
public function setTypes ( array $types )
{
$this -> types = $types ;
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Return the types .
*
* @ return array An array of FormTypeInterface
*/
2011-03-24 15:16:31 +00:00
public function getTypes ()
{
return $this -> types ;
}
2011-05-10 13:24:23 +01:00
/**
* Sets the data used for the client data when no value is bound .
*
* @ param mixed $emptyData
*/
2011-03-27 14:12:35 +01:00
public function setEmptyData ( $emptyData )
{
$this -> emptyData = $emptyData ;
return $this ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns the data used for the client data when no value is bound .
*
* @ return mixed
*/
2011-03-27 14:12:35 +01:00
public function getEmptyData ()
{
return $this -> emptyData ;
}
2011-03-18 15:34:54 +00:00
/**
* Adds a new field to this group . A field must have a unique name within
* the group . Otherwise the existing field is overwritten .
*
* If you add a nested group , this group should also be represented in the
2011-05-30 14:17:05 +01:00
* object hierarchy .
2011-03-18 15:34:54 +00:00
*
2011-05-10 13:24:23 +01:00
* @ param string | FormBuilder $child
2011-04-23 16:05:44 +01:00
* @ param string | FormTypeInterface $type
* @ param array $options
2011-05-10 13:24:23 +01:00
*
* @ return FormBuilder The current builder
2011-03-18 15:34:54 +00:00
*/
2011-04-24 09:54:50 +01:00
public function add ( $child , $type = null , array $options = array ())
2011-03-18 15:34:54 +00:00
{
2011-04-24 09:54:50 +01:00
if ( $child instanceof self ) {
$this -> children [ $child -> getName ()] = $child ;
return $this ;
}
if ( ! is_string ( $child )) {
throw new UnexpectedTypeException ( $child , 'string or Symfony\Component\Form\FormBuilder' );
2011-03-18 15:34:54 +00:00
}
2011-03-27 13:05:06 +01:00
if ( null !== $type && ! is_string ( $type ) && ! $type instanceof FormTypeInterface ) {
2011-04-22 16:41:21 +01:00
throw new UnexpectedTypeException ( $type , 'string or Symfony\Component\Form\FormTypeInterface' );
2011-03-19 18:42:16 +00:00
}
2011-04-24 09:54:50 +01:00
$this -> children [ $child ] = array (
2011-05-10 13:24:23 +01:00
'type' => $type ,
'options' => $options ,
2011-03-19 18:42:16 +00:00
);
return $this ;
}
2011-05-30 14:17:05 +01:00
/**
* Creates a form builder .
*
* @ param string $name The name of the form or the name of the property
* @ param string | FormTypeInterface $type The type of the form or null if name is a property
* @ param array $options The options
*
* @ return FormBuilder The builder
*
* @ throws FormException if the data class is not set when creating a property builder
*/
2011-04-24 09:54:50 +01:00
public function create ( $name , $type = null , array $options = array ())
2011-03-19 18:42:16 +00:00
{
2011-03-19 18:20:55 +00:00
if ( null !== $type ) {
2011-04-22 09:42:21 +01:00
$builder = $this -> getFormFactory () -> createNamedBuilder (
2011-03-19 18:42:16 +00:00
$type ,
$name ,
2011-04-22 09:42:21 +01:00
null ,
2011-03-19 18:42:16 +00:00
$options
);
} else {
if ( ! $this -> dataClass ) {
2011-06-09 10:33:25 +01:00
throw new FormException ( sprintf ( 'The "%s" type cannot be guessed as the data class is not set. Provide the type manually (\'text\', \'password\', ...) or set the data class.' , $name ));
2011-03-19 18:20:55 +00:00
}
2011-03-18 15:34:54 +00:00
2011-03-19 18:42:16 +00:00
$builder = $this -> getFormFactory () -> createBuilderForProperty (
$this -> dataClass ,
$name ,
2011-04-22 09:42:21 +01:00
null ,
2011-03-19 18:42:16 +00:00
$options
2011-03-18 15:34:54 +00:00
);
}
2011-03-19 18:42:16 +00:00
return $builder ;
2011-03-18 15:34:54 +00:00
}
2011-05-30 14:17:05 +01:00
/**
* Returns a child by name .
*
* @ param string $name The name of the child
*
* @ return FormBuilder The builder for the child
*
* @ throws FormException if the given child does not exist
*/
2011-03-18 15:34:54 +00:00
public function get ( $name )
{
2011-03-25 01:12:01 +00:00
if ( ! isset ( $this -> children [ $name ])) {
2011-03-18 15:34:54 +00:00
throw new FormException ( sprintf ( 'The field "%s" does not exist' , $name ));
}
2011-04-24 09:54:50 +01:00
if ( ! $this -> children [ $name ] instanceof FormBuilder ) {
2011-05-10 13:24:23 +01:00
$this -> children [ $name ] = $this -> create (
$name ,
2011-04-24 09:54:50 +01:00
$this -> children [ $name ][ 'type' ],
2011-05-10 13:24:23 +01:00
$this -> children [ $name ][ 'options' ]
);
2011-03-18 15:34:54 +00:00
}
2011-04-24 09:54:50 +01:00
return $this -> children [ $name ];
2011-03-18 15:34:54 +00:00
}
/**
* Removes the field with the given name .
*
* @ param string $name
2011-05-10 13:26:38 +01:00
*
* @ return FormBuilder The current builder
2011-03-18 15:34:54 +00:00
*/
public function remove ( $name )
{
2011-03-25 01:12:01 +00:00
if ( isset ( $this -> children [ $name ])) {
unset ( $this -> children [ $name ]);
2011-03-19 21:03:49 +00:00
}
2011-05-10 13:26:38 +01:00
return $this ;
2011-03-18 15:34:54 +00:00
}
/**
* Returns whether a field with the given name exists .
*
* @ param string $name
2011-05-10 13:24:23 +01:00
*
2011-03-18 15:34:54 +00:00
* @ return Boolean
*/
public function has ( $name )
{
2011-03-25 01:12:01 +00:00
return isset ( $this -> children [ $name ]);
2011-03-18 15:34:54 +00:00
}
2011-05-10 13:24:23 +01:00
/**
* Creates the form .
*
* @ return Form The form
*/
2011-03-20 14:16:53 +00:00
public function getForm ()
2011-03-18 15:34:54 +00:00
{
$instance = new Form (
$this -> getName (),
$this -> buildDispatcher (),
2011-03-31 14:23:33 +01:00
$this -> getTypes (),
2011-04-02 15:39:19 +01:00
$this -> getClientTransformers (),
$this -> getNormTransformers (),
2011-03-18 15:34:54 +00:00
$this -> getDataMapper (),
2011-03-20 11:00:19 +00:00
$this -> getValidators (),
2011-03-18 15:34:54 +00:00
$this -> getRequired (),
2011-03-20 09:35:16 +00:00
$this -> getReadOnly (),
2011-03-21 21:10:53 +00:00
$this -> getErrorBubbling (),
2011-03-27 14:12:35 +01:00
$this -> getEmptyData (),
2011-03-18 15:34:54 +00:00
$this -> getAttributes ()
);
2011-03-25 01:12:01 +00:00
foreach ( $this -> buildChildren () as $child ) {
$instance -> add ( $child );
2011-03-18 15:34:54 +00:00
}
if ( $this -> getData ()) {
$instance -> setData ( $this -> getData ());
}
return $instance ;
}
2011-05-10 13:24:23 +01:00
/**
* Returns the event dispatcher .
*
* @ return type
*/
protected function buildDispatcher ()
{
return $this -> dispatcher ;
}
/**
* Creates the children .
*
* @ return array An array of Form
*/
protected function buildChildren ()
{
$children = array ();
foreach ( $this -> children as $name => $builder ) {
if ( ! $builder instanceof FormBuilder ) {
$builder = $this -> create ( $name , $builder [ 'type' ], $builder [ 'options' ]);
}
$children [ $builder -> getName ()] = $builder -> getForm ();
}
return $children ;
}
2011-06-08 11:16:48 +01:00
}