[Form] Implemented support for buttons

This commit is contained in:
Bernhard Schussek 2012-12-31 15:29:36 +01:00
parent 9b6d30cf37
commit cc2118dd5c
33 changed files with 2081 additions and 201 deletions

View File

@ -218,6 +218,36 @@
{% endspaceless %}
{% endblock email_widget %}
{% block button_widget %}
{% spaceless %}
{% if type is not defined or type is empty %}
{% set type = "button" %}
{% endif %}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
<button type="{{ type }}" {{ block('button_attributes') }}>{{ label|trans({}, translation_domain) }}</button>
{% endspaceless %}
{% endblock button_widget %}
{% block submit_widget %}
{% spaceless %}
{% if type is not defined %}
{% set type = "submit" %}
{% endif %}
{{ block('button_widget') }}
{% endspaceless %}
{% endblock submit_widget %}
{% block reset_widget %}
{% spaceless %}
{% if type is not defined %}
{% set type = "reset" %}
{% endif %}
{{ block('button_widget') }}
{% endspaceless %}
{% endblock reset_widget %}
{# Labels #}
{% block form_label %}
@ -237,6 +267,8 @@
{% endspaceless %}
{% endblock form_label %}
{% block button_label %}{% endblock %}
{# Rows #}
{% block repeated_row %}
@ -259,6 +291,14 @@
{% endspaceless %}
{% endblock form_row %}
{% block button_row %}
{% spaceless %}
<div>
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock button_row %}
{% block hidden_row %}
{{ form_widget(form) }}
{% endblock hidden_row %}
@ -317,6 +357,13 @@
{% endspaceless %}
{% endblock widget_container_attributes %}
{% block button_attributes %}
{% spaceless %}
id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif %}
{% for attrname, attrvalue in attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
{% endspaceless %}
{% endblock button_attributes %}
{# Deprecated in Symfony 2.1, to be removed in 2.3 #}
{% block generic_label %}{{ block('form_label') }}{% endblock %}

View File

@ -14,6 +14,17 @@
{% endspaceless %}
{% endblock form_row %}
{% block button_row %}
{% spaceless %}
<tr>
<td></td>
<td colspan="2">
{{ form_widget(form) }}
</td>
</tr>
{% endspaceless %}
{% endblock button_row %}
{% block hidden_row %}
{% spaceless %}
<tr style="display: none">

View File

@ -140,6 +140,15 @@
<service id="form.type.url" class="Symfony\Component\Form\Extension\Core\Type\UrlType">
<tag name="form.type" alias="url" />
</service>
<service id="form.type.button" class="Symfony\Component\Form\Extension\Core\Type\ButtonType">
<tag name="form.type" alias="button" />
</service>
<service id="form.type.submit" class="Symfony\Component\Form\Extension\Core\Type\SubmitType">
<tag name="form.type" alias="submit" />
</service>
<service id="form.type.reset" class="Symfony\Component\Form\Extension\Core\Type\ResetType">
<tag name="form.type" alias="reset" />
</service>
<!-- FormTypeHttpFoundationExtension -->
<service id="form.type_extension.form.http_foundation" class="Symfony\Component\Form\Extension\HttpFoundation\Type\FormTypeHttpFoundationExtension">

View File

@ -0,0 +1,6 @@
id="<?php echo $view->escape($id) ?>"
name="<?php echo $view->escape($full_name) ?>"
<?php if ($disabled): ?>disabled="disabled" <?php endif ?>
<?php foreach ($attr as $k => $v): ?>
<?php printf('%s="%s" ', $view->escape($k), $view->escape($v)) ?>
<?php endforeach; ?>

View File

@ -0,0 +1,3 @@
<div>
<?php echo $view['form']->widget($form) ?>
</div>

View File

@ -0,0 +1,4 @@
<?php if (!$label) { $label = $view['form']->humanize($name); } ?>
<button type="<?php echo isset($type) ? $view->escape($type) : 'button' ?>" <?php echo $view['form']->block($form, 'button_attributes') ?>>
<?php $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?>
</button>

View File

@ -0,0 +1 @@
<?php echo $view['form']->block($form, 'button_widget', array('type' => isset($type) ? $type : 'reset')) ?>

View File

@ -0,0 +1 @@
<?php echo $view['form']->block($form, 'button_widget', array('type' => isset($type) ? $type : 'submit')) ?>

View File

@ -0,0 +1,6 @@
<tr>
<td></td>
<td>
<?php echo $view['form']->widget($form) ?>
</td>
</tr>

View File

@ -0,0 +1,412 @@
<?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;
use Symfony\Component\Form\Exception\AlreadyBoundException;
/**
* Default implementation of {@link ButtonInterface}.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class Button implements \IteratorAggregate, FormInterface
{
/**
* @var FormInterface
*/
private $parent;
/**
* @var FormConfigInterface
*/
private $config;
/**
* @var Boolean
*/
private $bound = false;
/**
* Creates a new button from a form configuration.
*
* @param FormConfigInterface $config The button's configuration.
*/
public function __construct(FormConfigInterface $config)
{
$this->config = $config;
}
/**
* Unsupported method.
*
* @param mixed $offset
*
* @return Boolean Always returns false.
*/
public function offsetExists($offset)
{
return false;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param mixed $offset
*
* @throws \BadMethodCallException
*/
public function offsetGet($offset)
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param mixed $offset
* @param mixed $value
*
* @throws \BadMethodCallException
*/
public function offsetSet($offset, $value)
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param mixed $offset
*
* @throws \BadMethodCallException
*/
public function offsetUnset($offset)
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* {@inheritdoc}
*/
public function setParent(FormInterface $parent = null)
{
$this->parent = $parent;
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return $this->parent;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param int|string|FormInterface $child
* @param null $type
* @param array $options
*
* @throws \BadMethodCallException
*/
public function add($child, $type = null, array $options = array())
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string $name
*
* @throws \BadMethodCallException
*/
public function get($name)
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* @param string $name
*
* @return Boolean Always returns false.
*/
public function has($name)
{
return false;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string $name
*
* @throws \BadMethodCallException
*/
public function remove($name)
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* {@inheritdoc}
*/
public function all()
{
return array();
}
/**
* {@inheritdoc}
*/
public function getErrors()
{
return array();
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string $modelData
*
* @throws \BadMethodCallException
*/
public function setData($modelData)
{
throw new \BadMethodCallException('Buttons cannot have data.');
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getData()
{
return null;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getNormData()
{
return null;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getViewData()
{
return null;
}
/**
* Unsupported method.
*
* @return array Always returns an empty array.
*/
public function getExtraData()
{
return array();
}
/**
* Returns the button's configuration.
*
* @return FormConfigInterface The configuration.
*/
public function getConfig()
{
return $this->config;
}
/**
* Returns whether the button is submitted.
*
* @return Boolean true if the button was submitted.
*/
public function isBound()
{
return $this->bound;
}
/**
* Returns the name by which the button is identified in forms.
*
* @return string The name of the button.
*/
public function getName()
{
return $this->config->getName();
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getPropertyPath()
{
return null;
}
/**
* Unsupported method.
*
* @param FormError $error
*
* @throws \BadMethodCallException
*/
public function addError(FormError $error)
{
throw new \BadMethodCallException('Buttons cannot have errors.');
}
/**
* Unsupported method.
*
* @return Boolean Always returns true.
*/
public function isValid()
{
return true;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function isRequired()
{
return false;
}
/**
* {@inheritdoc}
*/
public function isDisabled()
{
return $this->config->getDisabled();
}
/**
* Unsupported method.
*
* @return Boolean Always returns true.
*/
public function isEmpty()
{
return true;
}
/**
* Unsupported method.
*
* @return Boolean Always returns true.
*/
public function isSynchronized()
{
return true;
}
/**
* Binds data to the button.
*
* @param null|string $submittedData The data
*
* @return Button The button instance
*
* @throws Exception\AlreadyBoundException If the form has already been bound.
*/
public function bind($submittedData)
{
if ($this->bound) {
throw new AlreadyBoundException('A form can only be bound once');
}
$this->bound = true;
return $this;
}
/**
* {@inheritdoc}
*/
public function getRoot()
{
return $this->parent ? $this->parent->getRoot() : $this;
}
/**
* {@inheritdoc}
*/
public function isRoot()
{
return null === $this->parent;
}
/**
* {@inheritdoc}
*/
public function createView(FormView $parent = null)
{
if (null === $parent && $this->parent) {
$parent = $this->parent->createView();
}
return $this->config->getType()->createView($this, $parent);
}
/**
* Unsupported method.
*
* @return integer Always returns 0.
*/
public function count()
{
return 0;
}
/**
* Unsupported method.
*
* @return \EmptyIterator Always returns an empty iterator.
*/
public function getIterator()
{
return new \EmptyIterator();
}
}

View File

@ -0,0 +1,823 @@
<?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;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Exception\FormException;
/**
* A builder for {@link Button} instances.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface
{
/**
* @var Boolean
*/
protected $locked = false;
/**
* @var Boolean
*/
private $disabled;
/**
* @var ResolvedFormTypeInterface
*/
private $type;
/**
* @var string
*/
private $name;
/**
* @var array
*/
private $attributes = array();
/**
* @var array
*/
private $options;
/**
* Creates a new button builder.
*
* @param string $name The name of the button.
* @param array $options The button's options.
*
* @throws FormException If the name is empty.
*/
public function __construct($name, array $options)
{
if (empty($name) && 0 != $name) {
throw new FormException('Buttons cannot have empty names.');
}
$this->name = (string) $name;
$this->options = $options;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string|integer|FormBuilderInterface $child
* @param string|FormTypeInterface $type
* @param array $options
*
* @throws \BadMethodCallException
*/
public function add($child, $type = null, array $options = array())
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string $name
* @param string|FormTypeInterface $type
* @param array $options
*
* @throws \BadMethodCallException
*/
public function create($name, $type = null, array $options = array())
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string $name
*
* @throws \BadMethodCallException
*/
public function get($name)
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string $name
*
* @throws \BadMethodCallException
*/
public function remove($name)
{
throw new \BadMethodCallException('Buttons cannot have children.');
}
/**
* Unsupported method.
*
* @param string $name
*
* @return Boolean Always returns false.
*/
public function has($name)
{
return false;
}
/**
* Returns the children.
*
* @return array Always returns an empty array.
*/
public function all()
{
return array();
}
/**
* Creates the button.
*
* @return Button The button
*/
public function getForm()
{
return new Button($this->getFormConfig());
}
/**
* Unsupported method.
*
* Does nothing.
*
* @param FormBuilderInterface $parent The parent builder
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3. You
* should not rely on the parent of a builder, because it is
* likely that the parent is only set after turning the builder
* into a form.
*/
public function setParent(FormBuilderInterface $parent = null)
{
}
/**
* Unsupported method.
*
* @return null Always returns null.
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3. You
* should not rely on the parent of a builder, because it is
* likely that the parent is only set after turning the builder
* into a form.
*/
public function getParent()
{
return null;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*
* @deprecated Deprecated since version 2.2, to be removed in 2.3. You
* should not rely on the parent of a builder, because it is
* likely that the parent is only set after turning the builder
* into a form.
*/
public function hasParent()
{
return false;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param string $eventName
* @param callable $listener
* @param integer $priority
*
* @throws \BadMethodCallException
*/
public function addEventListener($eventName, $listener, $priority = 0)
{
throw new \BadMethodCallException('Buttons do not support event listeners.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param EventSubscriberInterface $subscriber
*
* @throws \BadMethodCallException
*/
public function addEventSubscriber(EventSubscriberInterface $subscriber)
{
throw new \BadMethodCallException('Buttons do not support event subscribers.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param FormValidatorInterface $validator
*
* @throws \BadMethodCallException
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
public function addValidator(FormValidatorInterface $validator)
{
throw new \BadMethodCallException('Buttons do not support validators.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param DataTransformerInterface $viewTransformer
* @param Boolean $forcePrepend
*
* @throws \BadMethodCallException
*/
public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false)
{
throw new \BadMethodCallException('Buttons do not support data transformers.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @throws \BadMethodCallException
*/
public function resetViewTransformers()
{
throw new \BadMethodCallException('Buttons do not support data transformers.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param DataTransformerInterface $modelTransformer
* @param Boolean $forceAppend
*
* @throws \BadMethodCallException
*/
public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false)
{
throw new \BadMethodCallException('Buttons do not support data transformers.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @throws \BadMethodCallException
*/
public function resetModelTransformers()
{
throw new \BadMethodCallException('Buttons do not support data transformers.');
}
/**
* {@inheritdoc}
*/
public function setAttribute($name, $value)
{
$this->attributes[$name] = $value;
}
/**
* {@inheritdoc}
*/
public function setAttributes(array $attributes)
{
$this->attributes = $attributes;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param DataMapperInterface $dataMapper
*
* @throws \BadMethodCallException
*/
public function setDataMapper(DataMapperInterface $dataMapper = null)
{
throw new \BadMethodCallException('Buttons do not support data mappers.');
}
/**
* Set whether the button is disabled.
*
* @param Boolean $disabled Whether the button is disabled
*
* @return ButtonBuilder The button builder.
*/
public function setDisabled($disabled)
{
$this->disabled = $disabled;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param mixed $emptyData
*
* @throws \BadMethodCallException
*/
public function setEmptyData($emptyData)
{
throw new \BadMethodCallException('Buttons do not support empty data.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param Boolean $errorBubbling
*
* @throws \BadMethodCallException
*/
public function setErrorBubbling($errorBubbling)
{
throw new \BadMethodCallException('Buttons do not support error bubbling.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param Boolean $required
*
* @throws \BadMethodCallException
*/
public function setRequired($required)
{
throw new \BadMethodCallException('Buttons cannot be required.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param null $propertyPath
*
* @throws \BadMethodCallException
*/
public function setPropertyPath($propertyPath)
{
throw new \BadMethodCallException('Buttons do not support property paths.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param Boolean $mapped
*
* @throws \BadMethodCallException
*/
public function setMapped($mapped)
{
throw new \BadMethodCallException('Buttons do not support data mapping.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param Boolean $byReference
*
* @throws \BadMethodCallException
*/
public function setByReference($byReference)
{
throw new \BadMethodCallException('Buttons do not support data mapping.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param Boolean $virtual
*
* @throws \BadMethodCallException
*/
public function setVirtual($virtual)
{
throw new \BadMethodCallException('Buttons cannot be virtual.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param Boolean $compound
*
* @throws \BadMethodCallException
*/
public function setCompound($compound)
{
throw new \BadMethodCallException('Buttons cannot be compound.');
}
/**
* Sets the type of the button.
*
* @param ResolvedFormTypeInterface $type The type of the button.
*
* @return ButtonBuilder The button builder.
*/
public function setType(ResolvedFormTypeInterface $type)
{
$this->type = $type;
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param array $data
*
* @throws \BadMethodCallException
*/
public function setData($data)
{
throw new \BadMethodCallException('Buttons do not support data.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param Boolean $locked
*
* @throws \BadMethodCallException
*/
public function setDataLocked($locked)
{
throw new \BadMethodCallException('Buttons do not support data locking.');
}
/**
* Unsupported method.
*
* This method should not be invoked.
*
* @param FormFactoryInterface $formFactory
*
* @return void
*
* @throws \BadMethodCallException
*/
public function setFormFactory(FormFactoryInterface $formFactory)
{
throw new \BadMethodCallException('Buttons do not support form factories.');
}
/**
* Builds and returns the button configuration.
*
* @return FormConfigInterface
*/
public function getFormConfig()
{
// This method should be idempotent, so clone the builder
$config = clone $this;
$config->locked = true;
return $config;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getEventDispatcher()
{
return null;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->name;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getPropertyPath()
{
return null;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function getMapped()
{
return false;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function getByReference()
{
return false;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function getVirtual()
{
return false;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function getCompound()
{
return false;
}
/**
* Returns the form type used to construct the button.
*
* @return ResolvedFormTypeInterface The button's type.
*/
public function getType()
{
return $this->type;
}
/**
* Unsupported method.
*
* @return array Always returns an empty array.
*/
public function getViewTransformers()
{
return array();
}
/**
* Unsupported method.
*
* @return array Always returns an empty array.
*/
public function getModelTransformers()
{
return array();
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getDataMapper()
{
return null;
}
/**
* Unsupported method.
*
* @return array Always returns null.
*
* @deprecated Deprecated since version 2.1, to be removed in 2.3.
*/
public function getValidators()
{
return array();
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function getRequired()
{
return false;
}
/**
* Returns whether the button is disabled.
*
* @return Boolean Whether the button is disabled.
*/
public function getDisabled()
{
return $this->disabled;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function getErrorBubbling()
{
return false;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getEmptyData()
{
return null;
}
/**
* Returns additional attributes of the button.
*
* @return array An array of key-value combinations.
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* Returns whether the attribute with the given name exists.
*
* @param string $name The attribute name.
*
* @return Boolean Whether the attribute exists.
*/
public function hasAttribute($name)
{
return isset($this->attributes[$name]);
}
/**
* Returns the value of the given attribute.
*
* @param string $name The attribute name.
* @param mixed $default The value returned if the attribute does not exist.
*
* @return mixed The attribute value.
*/
public function getAttribute($name, $default = null)
{
return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getData()
{
return null;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getDataClass()
{
return null;
}
/**
* Unsupported method.
*
* @return Boolean Always returns false.
*/
public function getDataLocked()
{
return false;
}
/**
* Unsupported method.
*
* @return null Always returns null.
*/
public function getFormFactory()
{
return null;
}
/**
* Returns all options passed during the construction of the button.
*
* @return array The passed options.
*/
public function getOptions()
{
return $this->options;
}
/**
* Returns whether a specific option exists.
*
* @param string $name The option name,
*
* @return Boolean Whether the option exists.
*/
public function hasOption($name)
{
return isset($this->options[$name]);
}
/**
* Returns the value of a specific option.
*
* @param string $name The option name.
* @param mixed $default The value returned if the option does not exist.
*
* @return mixed The option value.
*/
public function getOption($name, $default = null)
{
return isset($this->options[$name]) ? $this->options[$name] : $default;
}
/**
* Unsupported method.
*
* @return integer Always returns 0.
*/
public function count()
{
return 0;
}
/**
* Unsupported method.
*
* @return \EmptyIterator Always returns an empty iterator.
*/
public function getIterator()
{
return new \EmptyIterator();
}
}

View File

@ -0,0 +1,21 @@
<?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;
/**
* A type that should be converted into a {@link Button} instance.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface ButtonTypeInterface extends FormTypeInterface
{
}

View File

@ -0,0 +1,27 @@
<?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;
/**
* A clickable form element.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface ClickableInterface
{
/**
* Returns whether this element was clicked.
*
* @return Boolean Whether this element was clicked.
*/
public function isClicked();
}

View File

@ -50,6 +50,9 @@ class CoreExtension extends AbstractExtension
new Type\TimezoneType(),
new Type\UrlType(),
new Type\FileType(),
new Type\ButtonType(),
new Type\SubmitType(),
new Type\ResetType(),
);
}
}

View File

@ -0,0 +1,123 @@
<?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\Extension\Core\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
/**
* Encapsulates common logic of {@link FormType} and {@link ButtonType}.
*
* This type does not appear in the form's type inheritance chain and as such
* cannot be extended (via {@link FormTypeExtension}s) nor themed.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class BaseType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->setDisabled($options['disabled']);
}
/**
* {@inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
/* @var \Symfony\Component\Form\ClickableInterface $form */
$name = $form->getName();
$blockName = $options['block_name'] ?: $form->getName();
$translationDomain = $options['translation_domain'];
if ($view->parent) {
if ('' !== ($parentFullName = $view->parent->vars['full_name'])) {
$id = sprintf('%s_%s', $view->parent->vars['id'], $name);
$fullName = sprintf('%s[%s]', $parentFullName, $name);
$uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName);
} else {
$id = $name;
$fullName = $name;
$uniqueBlockPrefix = '_'.$blockName;
}
if (!$translationDomain) {
$translationDomain = $view->parent->vars['translation_domain'];
}
} else {
$id = $name;
$fullName = $name;
$uniqueBlockPrefix = '_'.$blockName;
// Strip leading underscores and digits. These are allowed in
// form names, but not in HTML4 ID attributes.
// http://www.w3.org/TR/html401/struct/global.html#adef-id
$id = ltrim($id, '_0123456789');
}
$blockPrefixes = array();
for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) {
array_unshift($blockPrefixes, $type->getName());
}
$blockPrefixes[] = $uniqueBlockPrefix;
if (!$translationDomain) {
$translationDomain = 'messages';
}
$view->vars = array_replace($view->vars, array(
'form' => $view,
'id' => $id,
'name' => $name,
'full_name' => $fullName,
'disabled' => $form->isDisabled(),
'label' => $options['label'],
'multipart' => false,
'attr' => $options['attr'],
'block_prefixes' => $blockPrefixes,
'unique_block_prefix' => $uniqueBlockPrefix,
'translation_domain' => $translationDomain,
// Using the block name here speeds up performance in collection
// forms, where each entry has the same full block name.
// Including the type is important too, because if rows of a
// collection form have different types (dynamically), they should
// be rendered differently.
// https://github.com/symfony/symfony/issues/5038
'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(),
));
}
/**
* {@inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'block_name' => null,
'disabled' => false,
'label' => null,
'attr' => array(),
'translation_domain' => null,
));
$resolver->setAllowedTypes(array(
'attr' => 'array',
));
}
}

View File

@ -0,0 +1,38 @@
<?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\Extension\Core\Type;
use Symfony\Component\Form\ButtonTypeInterface;
/**
* A form button.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ButtonType extends BaseType implements ButtonTypeInterface
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return null;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'button';
}
}

View File

@ -11,7 +11,6 @@
namespace Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
@ -23,7 +22,7 @@ use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
class FormType extends AbstractType
class FormType extends BaseType
{
/**
* @var PropertyAccessorInterface
@ -40,9 +39,10 @@ class FormType extends AbstractType
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->setRequired($options['required'])
->setDisabled($options['disabled'])
->setErrorBubbling($options['error_bubbling'])
->setEmptyData($options['empty_data'])
->setPropertyPath($options['property_path'])
@ -65,85 +65,34 @@ class FormType extends AbstractType
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
parent::buildView($view, $form, $options);
$name = $form->getName();
$blockName = $options['block_name'] ?: $form->getName();
$readOnly = $options['read_only'];
$translationDomain = $options['translation_domain'];
if ($view->parent) {
if ('' === $name) {
throw new Exception('Form node with empty name can be used only as root form node.');
}
if ('' !== ($parentFullName = $view->parent->vars['full_name'])) {
$id = sprintf('%s_%s', $view->parent->vars['id'], $name);
$fullName = sprintf('%s[%s]', $parentFullName, $name);
$uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName);
} else {
$id = $name;
$fullName = $name;
$uniqueBlockPrefix = '_'.$blockName;
}
// Complex fields are read-only if they themselves or their parents are.
if (!$readOnly) {
$readOnly = $view->parent->vars['read_only'];
}
if (!$translationDomain) {
$translationDomain = $view->parent->vars['translation_domain'];
}
} else {
$id = $name;
$fullName = $name;
$uniqueBlockPrefix = '_'.$blockName;
// Strip leading underscores and digits. These are allowed in
// form names, but not in HTML4 ID attributes.
// http://www.w3.org/TR/html401/struct/global.html#adef-id
$id = ltrim($id, '_0123456789');
}
$blockPrefixes = array();
for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) {
array_unshift($blockPrefixes, $type->getName());
}
$blockPrefixes[] = $uniqueBlockPrefix;
if (!$translationDomain) {
$translationDomain = 'messages';
}
$view->vars = array_replace($view->vars, array(
'form' => $view,
'id' => $id,
'name' => $name,
'full_name' => $fullName,
'read_only' => $readOnly,
'errors' => $form->getErrors(),
'valid' => $form->isBound() ? $form->isValid() : true,
'value' => $form->getViewData(),
'data' => $form->getNormData(),
'disabled' => $form->isDisabled(),
'required' => $form->isRequired(),
'max_length' => $options['max_length'],
'pattern' => $options['pattern'],
'size' => null,
'label' => $options['label'],
'multipart' => false,
'attr' => $options['attr'],
'label_attr' => $options['label_attr'],
'compound' => $form->getConfig()->getCompound(),
'block_prefixes' => $blockPrefixes,
'unique_block_prefix' => $uniqueBlockPrefix,
'translation_domain' => $translationDomain,
// Using the block name here speeds up performance in collection
// forms, where each entry has the same full block name.
// Including the type is important too, because if rows of a
// collection form have different types (dynamically), they should
// be rendered differently.
// https://github.com/symfony/symfony/issues/5038
'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(),
'read_only' => $readOnly,
'errors' => $form->getErrors(),
'valid' => $form->isBound() ? $form->isValid() : true,
'value' => $form->getViewData(),
'data' => $form->getNormData(),
'required' => $form->isRequired(),
'max_length' => $options['max_length'],
'pattern' => $options['pattern'],
'size' => null,
'label_attr' => $options['label_attr'],
'compound' => $form->getConfig()->getCompound(),
));
}
@ -169,6 +118,8 @@ class FormType extends AbstractType
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
parent::setDefaultOptions($resolver);
// Derive "data_class" option from passed "data" object
$dataClass = function (Options $options) {
return isset($options['data']) && is_object($options['data']) ? get_class($options['data']) : null;
@ -202,29 +153,23 @@ class FormType extends AbstractType
));
$resolver->setDefaults(array(
'block_name' => null,
'data_class' => $dataClass,
'empty_data' => $emptyData,
'trim' => true,
'required' => true,
'read_only' => false,
'disabled' => false,
'max_length' => null,
'pattern' => null,
'property_path' => null,
'mapped' => true,
'by_reference' => true,
'error_bubbling' => $errorBubbling,
'label' => null,
'attr' => array(),
'label_attr' => array(),
'virtual' => false,
'compound' => true,
'translation_domain' => null,
));
$resolver->setAllowedTypes(array(
'attr' => 'array',
'label_attr' => 'array',
));
}

View File

@ -0,0 +1,39 @@
<?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\Extension\Core\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\ButtonTypeInterface;
/**
* A reset button.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ResetType extends AbstractType implements ButtonTypeInterface
{
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'button';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'reset';
}
}

View File

@ -0,0 +1,46 @@
<?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\Extension\Core\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\SubmitButtonTypeInterface;
/**
* A submit button.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class SubmitType extends AbstractType implements SubmitButtonTypeInterface
{
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['clicked'] = $form->isClicked();
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return 'button';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'submit';
}
}

View File

@ -53,17 +53,9 @@ class FormTypeValidatorExtension extends AbstractTypeExtension
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
// Make sure that validation groups end up as null, closure or array
$validationGroupsNormalizer = function (Options $options, $groups) {
if (empty($groups)) {
return null;
}
if (is_callable($groups)) {
return $groups;
}
return (array) $groups;
// BC clause
$constraints = function (Options $options) {
return $options['validation_constraint'];
};
// Constraint should always be converted to an array
@ -73,8 +65,9 @@ class FormTypeValidatorExtension extends AbstractTypeExtension
$resolver->setDefaults(array(
'error_mapping' => array(),
'validation_groups' => null,
'constraints' => null,
// "validation_constraint" is deprecated. Use "constraints".
'validation_constraint' => null,
'constraints' => $constraints,
'cascade_validation' => false,
'invalid_message' => 'This value is not valid.',
'invalid_message_parameters' => array(),
@ -83,7 +76,6 @@ class FormTypeValidatorExtension extends AbstractTypeExtension
));
$resolver->setNormalizers(array(
'validation_groups' => $validationGroupsNormalizer,
'constraints' => $constraintsNormalizer,
));
}

View File

@ -150,9 +150,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
public function getConfig();
/**
* Returns whether the field is bound.
* Returns whether the form is submitted.
*
* @return Boolean true if the form is bound to input values, false otherwise
* @return Boolean true if the form is submitted, false otherwise
*/
public function isBound();

View File

@ -111,7 +111,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface
// Should be decoupled from the specific option at some point
$dataClass = isset($options['data_class']) ? $options['data_class'] : null;
$builder = new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options);
$builder = $this->newBuilder($name, $dataClass, $factory, $options);
$builder->setType($this);
$builder->setParent($parent);
@ -127,7 +127,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface
{
$options = $form->getConfig()->getOptions();
$view = new FormView($parent);
$view = $this->newView($parent);
$this->buildView($view, $form, $options);
@ -243,4 +243,43 @@ class ResolvedFormType implements ResolvedFormTypeInterface
return $this->optionsResolver;
}
/**
* Creates a new builder instance.
*
* Override this method if you want to customize the builder class.
*
* @param string $name The name of the builder.
* @param string $dataClass The data class.
* @param FormFactoryInterface $factory The current form factory.
* @param array $options The builder options.
*
* @return FormBuilderInterface The new builder instance.
*/
protected function newBuilder($name, $dataClass, FormFactoryInterface $factory, array $options)
{
if ($this->innerType instanceof ButtonTypeInterface) {
return new ButtonBuilder($name, $options);
}
if ($this->innerType instanceof SubmitButtonTypeInterface) {
return new SubmitButtonBuilder($name, $options);
}
return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options);
}
/**
* Creates a new view instance.
*
* Override this method if you want to customize the view class.
*
* @param FormView|null $parent The parent view, if available.
*
* @return FormView A new view instance.
*/
protected function newView(FormView $parent = null)
{
return new FormView($parent);
}
}

View File

@ -0,0 +1,51 @@
<?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;
/**
* A button that submits the form.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class SubmitButton extends Button implements ClickableInterface
{
/**
* @var Boolean
*/
private $clicked = false;
/**
* {@inheritdoc}
*/
public function isClicked()
{
return $this->clicked;
}
/**
* Binds data to the button.
*
* @param null|string $submittedData The data
*
* @return SubmitButton The button instance
*
* @throws Exception\AlreadyBoundException If the form has already been bound.
*/
public function bind($submittedData)
{
parent::bind($submittedData);
$this->clicked = null !== $submittedData;
return $this;
}
}

View File

@ -0,0 +1,30 @@
<?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;
/**
* A builder for {@link SubmitButton} instances.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class SubmitButtonBuilder extends ButtonBuilder
{
/**
* Creates the button.
*
* @return Button The button
*/
public function getForm()
{
return new SubmitButton($this->getFormConfig());
}
}

View File

@ -0,0 +1,21 @@
<?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;
/**
* A type that should be converted into a {@link SubmitButton} instance.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface SubmitButtonTypeInterface extends FormTypeInterface
{
}

View File

@ -82,6 +82,22 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest
);
}
public function testButtonRow()
{
$form = $this->factory->createNamed('name', 'button');
$view = $form->createView();
$html = $this->renderRow($view);
$this->assertMatchesXpath($html,
'/div
[
./button[@type="button"][@name="name"]
]
[count(//label)=0]
'
);
}
public function testRest()
{
$view = $this->factory->createNamedBuilder('name', 'form')

View File

@ -1762,4 +1762,38 @@ abstract class AbstractLayoutTest extends FormIntegrationTestCase
//input[@type="text"][@id="child"][@name="child"]'
, 2);
}
public function testButton()
{
$form = $this->factory->createNamed('name', 'button');
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/button[@type="button"][@name="name"]'
);
}
public function testButtonLabelIsEmpty()
{
$form = $this->factory->createNamed('name', 'button');
$this->assertSame('', $this->renderLabel($form->createView()));
}
public function testSubmit()
{
$form = $this->factory->createNamed('name', 'submit');
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/button[@type="submit"][@name="name"]'
);
}
public function testReset()
{
$form = $this->factory->createNamed('name', 'reset');
$this->assertWidgetMatchesXpath($form->createView(), array(),
'/button[@type="reset"][@name="name"]'
);
}
}

View File

@ -125,6 +125,25 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest
);
}
public function testButtonRow()
{
$form = $this->factory->createNamed('name', 'button');
$view = $form->createView();
$html = $this->renderRow($view);
$this->assertMatchesXpath($html,
'/tr
[
./td
[.=""]
/following-sibling::td
[./button[@type="button"][@name="name"]]
]
[count(//label)=0]
'
);
}
public function testRest()
{
$view = $this->factory->createNamedBuilder('name', 'form')

View File

@ -0,0 +1,129 @@
<?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\Tests\Extension\Core\Type;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
abstract class BaseTypeTest extends TypeTestCase
{
public function testPassDisabledAsOption()
{
$form = $this->factory->create($this->getTestedType(), null, array('disabled' => true));
$this->assertTrue($form->isDisabled());
}
public function testPassIdAndNameToView()
{
$form = $this->factory->createNamed('name', $this->getTestedType());
$view = $form->createView();
$this->assertEquals('name', $view->vars['id']);
$this->assertEquals('name', $view->vars['name']);
$this->assertEquals('name', $view->vars['full_name']);
}
public function testStripLeadingUnderscoresAndDigitsFromId()
{
$form = $this->factory->createNamed('_09name', $this->getTestedType());
$view = $form->createView();
$this->assertEquals('name', $view->vars['id']);
$this->assertEquals('_09name', $view->vars['name']);
$this->assertEquals('_09name', $view->vars['full_name']);
}
public function testPassIdAndNameToViewWithParent()
{
$parent = $this->factory->createNamed('parent', 'form');
$parent->add($this->factory->createNamed('child', $this->getTestedType()));
$view = $parent->createView();
$this->assertEquals('parent_child', $view['child']->vars['id']);
$this->assertEquals('child', $view['child']->vars['name']);
$this->assertEquals('parent[child]', $view['child']->vars['full_name']);
}
public function testPassIdAndNameToViewWithGrandParent()
{
$parent = $this->factory->createNamed('parent', 'form');
$parent->add($this->factory->createNamed('child', 'form'));
$parent['child']->add($this->factory->createNamed('grand_child', $this->getTestedType()));
$view = $parent->createView();
$this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']);
$this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']);
$this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']);
}
public function testPassTranslationDomainToView()
{
$form = $this->factory->create($this->getTestedType(), null, array(
'translation_domain' => 'domain',
));
$view = $form->createView();
$this->assertSame('domain', $view->vars['translation_domain']);
}
public function testInheritTranslationDomainFromParent()
{
$parent = $this->factory->createNamed('parent', 'form', null, array(
'translation_domain' => 'domain',
));
$child = $this->factory->createNamed('child', $this->getTestedType());
$view = $parent->add($child)->createView();
$this->assertEquals('domain', $view['child']->vars['translation_domain']);
}
public function testPreferOwnTranslationDomain()
{
$parent = $this->factory->createNamed('parent', 'form', null, array(
'translation_domain' => 'parent_domain',
));
$child = $this->factory->createNamed('child', $this->getTestedType(), null, array(
'translation_domain' => 'domain',
));
$view = $parent->add($child)->createView();
$this->assertEquals('domain', $view['child']->vars['translation_domain']);
}
public function testDefaultTranslationDomain()
{
$parent = $this->factory->createNamed('parent', 'form');
$child = $this->factory->createNamed('child', $this->getTestedType());
$view = $parent->add($child)->createView();
$this->assertEquals('messages', $view['child']->vars['translation_domain']);
}
public function testPassLabelToView()
{
$form = $this->factory->createNamed('__test___field', $this->getTestedType(), null, array('label' => 'My label'));
$view = $form->createView();
$this->assertSame('My label', $view->vars['label']);
}
public function testPassMultipartFalseToView()
{
$form = $this->factory->create($this->getTestedType());
$view = $form->createView();
$this->assertFalse($view->vars['multipart']);
}
abstract protected function getTestedType();
}

View File

@ -0,0 +1,28 @@
<?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\Tests\Extension\Core\Type;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ButtonTypeTest extends BaseTypeTest
{
public function testCreateButtonInstances()
{
$this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create('button'));
}
protected function getTestedType()
{
return 'button';
}
}

View File

@ -50,8 +50,13 @@ class FormTest_AuthorWithoutRefSetter
}
}
class FormTypeTest extends TypeTestCase
class FormTypeTest extends BaseTypeTest
{
public function testCreateFormInstances()
{
$this->assertInstanceOf('Symfony\Component\Form\Form', $this->factory->create('form'));
}
public function testPassRequiredAsOption()
{
$form = $this->factory->create('form', null, array('required' => false));
@ -63,13 +68,6 @@ class FormTypeTest extends TypeTestCase
$this->assertTrue($form->isRequired());
}
public function testPassDisabledAsOption()
{
$form = $this->factory->create('form', null, array('disabled' => true));
$this->assertTrue($form->isDisabled());
}
public function testBoundDataIsTrimmedBeforeTransforming()
{
$form = $this->factory->createBuilder('form')
@ -102,49 +100,6 @@ class FormTypeTest extends TypeTestCase
$this->assertEquals('reverse[ a ]', $form->getData());
}
public function testPassIdAndNameToView()
{
$form = $this->factory->createNamed('name', 'form');
$view = $form->createView();
$this->assertEquals('name', $view->vars['id']);
$this->assertEquals('name', $view->vars['name']);
$this->assertEquals('name', $view->vars['full_name']);
}
public function testStripLeadingUnderscoresAndDigitsFromId()
{
$form = $this->factory->createNamed('_09name', 'form');
$view = $form->createView();
$this->assertEquals('name', $view->vars['id']);
$this->assertEquals('_09name', $view->vars['name']);
$this->assertEquals('_09name', $view->vars['full_name']);
}
public function testPassIdAndNameToViewWithParent()
{
$parent = $this->factory->createNamed('parent', 'form');
$parent->add($this->factory->createNamed('child', 'form'));
$view = $parent->createView();
$this->assertEquals('parent_child', $view['child']->vars['id']);
$this->assertEquals('child', $view['child']->vars['name']);
$this->assertEquals('parent[child]', $view['child']->vars['full_name']);
}
public function testPassIdAndNameToViewWithGrandParent()
{
$parent = $this->factory->createNamed('parent', 'form');
$parent->add($this->factory->createNamed('child', 'form'));
$parent['child']->add($this->factory->createNamed('grand_child', 'form'));
$view = $parent->createView();
$this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']);
$this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']);
$this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']);
}
public function testNonReadOnlyFormWithReadOnlyParentBeingReadOnly()
{
$parent = $this->factory->createNamed('parent', 'form', null, array('read_only' => true));
@ -180,57 +135,6 @@ class FormTypeTest extends TypeTestCase
$this->assertSame(10, $view->vars['max_length']);
}
public function testPassTranslationDomainToView()
{
$form = $this->factory->create('form', null, array('translation_domain' => 'test'));
$view = $form->createView();
$this->assertSame('test', $view->vars['translation_domain']);
}
public function testNonTranslationDomainFormWithTranslationDomainParentBeingTranslationDomain()
{
$parent = $this->factory->createNamed('parent', 'form', null, array('translation_domain' => 'test'));
$child = $this->factory->createNamed('child', 'form');
$view = $parent->add($child)->createView();
$this->assertEquals('test', $view['child']->vars['translation_domain']);
}
public function testTranslationDomainFormWithNonTranslationDomainParentBeingTranslationDomain()
{
$parent = $this->factory->createNamed('parent', 'form');
$child = $this->factory->createNamed('child', 'form', null, array('translation_domain' => 'test'));
$view = $parent->add($child)->createView();
$this->assertEquals('test', $view['child']->vars['translation_domain']);
}
public function testNonTranslationDomainFormWithNonTranslationDomainParentBeingTranslationDomainDefault()
{
$parent = $this->factory->createNamed('parent', 'form');
$child = $this->factory->createNamed('child', 'form');
$view = $parent->add($child)->createView();
$this->assertEquals('messages', $view['child']->vars['translation_domain']);
}
public function testPassLabelToView()
{
$form = $this->factory->createNamed('__test___field', 'form', null, array('label' => 'My label'));
$view = $form->createView();
$this->assertSame('My label', $view->vars['label']);
}
public function testDefaultTranslationDomain()
{
$form = $this->factory->create('form');
$view = $form->createView();
$this->assertSame('messages', $view->vars['translation_domain']);
}
public function testBindWithEmptyDataCreatesObjectIfClassAvailable()
{
$form = $this->factory->create('form', null, array(
@ -404,6 +308,7 @@ class FormTypeTest extends TypeTestCase
$this->assertEquals('', $form->getName());
}
public function testSubformDoesntCallSetters()
{
$author = new FormTest_AuthorWithoutRefSetter(new Author());
@ -523,14 +428,6 @@ class FormTypeTest extends TypeTestCase
$this->assertSame($ref2, $author['referenceCopy']);
}
public function testPassMultipartFalseToView()
{
$form = $this->factory->create('form');
$view = $form->createView();
$this->assertFalse($view->vars['multipart']);
}
public function testPassMultipartTrueIfAnyChildIsMultipartToView()
{
$form = $this->factory->create('form');
@ -661,4 +558,9 @@ class FormTypeTest extends TypeTestCase
$this->assertSame('0', $view->vars['label']);
}
protected function getTestedType()
{
return 'form';
}
}

View File

@ -0,0 +1,54 @@
<?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\Tests\Extension\Core\Type;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class SubmitTypeTest extends TypeTestCase
{
public function testCreateSubmitButtonInstances()
{
$this->assertInstanceOf('Symfony\Component\Form\SubmitButton', $this->factory->create('submit'));
}
public function testNotClickedByDefault()
{
$button = $this->factory->create('submit');
$this->assertFalse($button->isClicked());
}
public function testNotClickedIfBoundWithNull()
{
$button = $this->factory->create('submit');
$button->bind(null);
$this->assertFalse($button->isClicked());
}
public function testClickedIfBoundWithEmptyString()
{
$button = $this->factory->create('submit');
$button->bind('');
$this->assertTrue($button->isClicked());
}
public function testClickedIfBoundWithUnemptyString()
{
$button = $this->factory->create('submit');
$button->bind('foo');
$this->assertTrue($button->isClicked());
}
}