From de253dd3dd8c37bff89564b856fdaa7efad4d816 Mon Sep 17 00:00:00 2001 From: Helmer Aaviksoo Date: Thu, 26 Jan 2012 17:54:42 +0200 Subject: [PATCH] [Form] read_only and disabled attributes --- CHANGELOG-2.1.md | 1 + .../views/Form/form_div_layout.html.twig | 2 +- .../Resources/views/Form/attributes.html.php | 3 +- .../Form/Extension/Core/Type/FieldType.php | 7 ++-- src/Symfony/Component/Form/Form.php | 31 +++++----------- src/Symfony/Component/Form/FormBuilder.php | 20 +++++------ src/Symfony/Component/Form/FormInterface.php | 14 ++++---- .../Component/Form/AbstractLayoutTest.php | 30 ++++++++++++++++ .../Extension/Core/Type/FieldTypeTest.php | 6 ++-- .../Tests/Component/Form/FormFactoryTest.php | 4 +-- .../Symfony/Tests/Component/Form/FormTest.php | 36 +++++++++---------- 11 files changed, 88 insertions(+), 66 deletions(-) diff --git a/CHANGELOG-2.1.md b/CHANGELOG-2.1.md index b54e3498e6..705a6dbb7a 100644 --- a/CHANGELOG-2.1.md +++ b/CHANGELOG-2.1.md @@ -158,6 +158,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c ### Form + * [BC BREAK] ``read_only`` field attribute now renders as ``readonly="readonly"``, use ``disabled`` instead * [BC BREAK] child forms now aren't validated anymore by default * made validation of form children configurable (new option: cascade_validation) * added support for validation groups as callbacks diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig index 3ba5fc5f4b..fe3a16aa1e 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig @@ -280,7 +280,7 @@ {% block widget_attributes %} {% spaceless %} - id="{{ id }}" name="{{ full_name }}"{% if read_only %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %} + id="{{ id }}" name="{{ full_name }}"{% if read_only %} readonly="readonly"{% endif %}{% if disabled %} disabled="disabled"{% endif %}{% if required %} required="required"{% endif %}{% if max_length %} maxlength="{{ max_length }}"{% endif %}{% if pattern %} pattern="{{ pattern }}"{% endif %} {% for attrname,attrvalue in attr %}{{attrname}}="{{attrvalue}}" {% endfor %} {% endspaceless %} {% endblock widget_attributes %} diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php index 33b3c7eac1..fe4afa01d2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/attributes.html.php @@ -1,6 +1,7 @@ id="escape($id) ?>" name="escape($full_name) ?>" -disabled="disabled" +readonly="readonly" +disabled="disabled" required="required" maxlength="escape($max_length) ?>" pattern="escape($pattern) ?>" diff --git a/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php b/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php index 05aaf230f1..f9f11a8d96 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/FieldType.php @@ -44,9 +44,10 @@ class FieldType extends AbstractType $builder ->setRequired($options['required']) - ->setReadOnly($options['read_only']) + ->setDisabled($options['disabled']) ->setErrorBubbling($options['error_bubbling']) ->setEmptyData($options['empty_data']) + ->setAttribute('read_only', $options['read_only']) ->setAttribute('by_reference', $options['by_reference']) ->setAttribute('property_path', $options['property_path']) ->setAttribute('error_mapping', $options['error_mapping']) @@ -102,7 +103,8 @@ class FieldType extends AbstractType ->set('full_name', $fullName) ->set('errors', $form->getErrors()) ->set('value', $form->getClientData()) - ->set('read_only', $form->isReadOnly()) + ->set('read_only', $form->getAttribute('read_only')) + ->set('disabled', $form->isDisabled()) ->set('required', $form->isRequired()) ->set('max_length', $form->getAttribute('max_length')) ->set('pattern', $form->getAttribute('pattern')) @@ -126,6 +128,7 @@ class FieldType extends AbstractType 'trim' => true, 'required' => true, 'read_only' => false, + 'disabled' => false, 'max_length' => null, 'pattern' => null, 'property_path' => null, diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index f477211d67..ecc62b719c 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -166,7 +166,7 @@ class Form implements \IteratorAggregate, FormInterface * Whether this form may only be read, but not bound * @var Boolean */ - private $readOnly = false; + private $disabled = false; /** * The dispatcher for distributing events of this form @@ -190,7 +190,7 @@ class Form implements \IteratorAggregate, FormInterface array $types = array(), array $clientTransformers = array(), array $normTransformers = array(), DataMapperInterface $dataMapper = null, array $validators = array(), - $required = false, $readOnly = false, $errorBubbling = false, + $required = false, $disabled = false, $errorBubbling = false, $emptyData = null, array $attributes = array()) { foreach ($clientTransformers as $transformer) { @@ -219,7 +219,7 @@ class Form implements \IteratorAggregate, FormInterface $this->dataMapper = $dataMapper; $this->validators = $validators; $this->required = (Boolean) $required; - $this->readOnly = (Boolean) $readOnly; + $this->disabled = (Boolean) $disabled; $this->errorBubbling = (Boolean) $errorBubbling; $this->emptyData = $emptyData; $this->attributes = $attributes; @@ -266,7 +266,6 @@ class Form implements \IteratorAggregate, FormInterface public function isRequired() { if (null === $this->parent || $this->parent->isRequired()) { - return $this->required; } @@ -274,21 +273,12 @@ class Form implements \IteratorAggregate, FormInterface } /** - * Returns whether this form is read only. - * - * The content of a read-only form is displayed, but not allowed to be - * modified. The validation of modified read-only forms should fail. - * - * Fields whose parents are read-only are considered read-only regardless of - * their own state. - * - * @return Boolean + * {@inheritDoc} */ - public function isReadOnly() + public function isDisabled() { - if (null === $this->parent || !$this->parent->isReadOnly()) { - - return $this->readOnly; + if (null === $this->parent || !$this->parent->isDisabled()) { + return $this->disabled; } return true; @@ -457,7 +447,7 @@ class Form implements \IteratorAggregate, FormInterface */ public function bind($clientData) { - if ($this->readOnly) { + if ($this->isDisabled()) { $this->bound = true; return $this; @@ -674,7 +664,6 @@ class Form implements \IteratorAggregate, FormInterface { foreach ($this->children as $child) { if (!$child->isEmpty()) { - return false; } } @@ -697,10 +686,9 @@ class Form implements \IteratorAggregate, FormInterface return false; } - if (!$this->readOnly) { + if (!$this->isDisabled()) { foreach ($this->children as $child) { if (!$child->isValid()) { - return false; } } @@ -865,7 +853,6 @@ class Form implements \IteratorAggregate, FormInterface public function get($name) { if (isset($this->children[$name])) { - return $this->children[$name]; } diff --git a/src/Symfony/Component/Form/FormBuilder.php b/src/Symfony/Component/Form/FormBuilder.php index b3fcfb41fd..e590048906 100644 --- a/src/Symfony/Component/Form/FormBuilder.php +++ b/src/Symfony/Component/Form/FormBuilder.php @@ -46,7 +46,7 @@ class FormBuilder /** * @var Boolean */ - private $readOnly; + private $disabled; /** * @var Boolean @@ -174,27 +174,27 @@ class FormBuilder } /** - * Set whether the form is read only + * Set whether the form is disabled * - * @param Boolean $readOnly Whether the form is read only + * @param Boolean $disabled Whether the form is disabled * * @return FormBuilder The current builder */ - public function setReadOnly($readOnly) + public function setDisabled($disabled) { - $this->readOnly = (Boolean) $readOnly; + $this->disabled = (Boolean) $disabled; return $this; } /** - * Returns whether the form is read only. + * Returns whether the form is disabled. * - * @return Boolean Whether the form is read only + * @return Boolean Whether the form is disabled */ - public function getReadOnly() + public function getDisabled() { - return $this->readOnly; + return $this->disabled; } /** @@ -645,7 +645,7 @@ class FormBuilder $this->getDataMapper(), $this->getValidators(), $this->getRequired(), - $this->getReadOnly(), + $this->getDisabled(), $this->getErrorBubbling(), $this->getEmptyData(), $this->getAttributes() diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index 75088731dd..d0d8a80a8d 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -48,9 +48,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable /** * Returns the child with the given name. - * + * * @param string $name The name of the child - * + * * @return FormInterface The child form */ function get($name); @@ -178,17 +178,17 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable function isRequired(); /** - * Returns whether this form can be read only. + * Returns whether this form is disabled. * - * The content of a read-only form is displayed, but not allowed to be - * modified. The validation of modified read-only forms should fail. + * The content of a disabled form is displayed, but not allowed to be + * modified. The validation of modified disabled forms should fail. * - * Fields whose parents are read-only are considered read-only regardless of + * Fields whose parents are disabled are considered disabled regardless of * their own state. * * @return Boolean */ - function isReadOnly(); + function isDisabled(); /** * Returns whether the form is empty. diff --git a/tests/Symfony/Tests/Component/Form/AbstractLayoutTest.php b/tests/Symfony/Tests/Component/Form/AbstractLayoutTest.php index 877bda7c0e..3c41237c17 100644 --- a/tests/Symfony/Tests/Component/Form/AbstractLayoutTest.php +++ b/tests/Symfony/Tests/Component/Form/AbstractLayoutTest.php @@ -1299,6 +1299,36 @@ abstract class AbstractLayoutTest extends \PHPUnit_Framework_TestCase ); } + public function testReadOnly() + { + $form = $this->factory->createNamed('text', 'name', null, array( + 'read_only' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@readonly="readonly"] +' + ); + } + + public function testDisabled() + { + $form = $this->factory->createNamed('text', 'name', null, array( + 'disabled' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/input + [@type="text"] + [@name="name"] + [@disabled="disabled"] +' + ); + } + public function testInteger() { $form = $this->factory->createNamed('integer', 'na&me', 123, array( diff --git a/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php b/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php index a308215e15..3cdc7c7553 100644 --- a/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php +++ b/tests/Symfony/Tests/Component/Form/Extension/Core/Type/FieldTypeTest.php @@ -70,11 +70,11 @@ class FieldTypeTest extends TypeTestCase $this->assertTrue($form->isRequired()); } - public function testPassReadOnlyAsOption() + public function testPassDisabledAsOption() { - $form = $this->factory->create('field', null, array('read_only' => true)); + $form = $this->factory->create('field', null, array('disabled' => true)); - $this->assertTrue($form->isReadOnly()); + $this->assertTrue($form->isDisabled()); } public function testBoundDataIsTrimmedBeforeTransforming() diff --git a/tests/Symfony/Tests/Component/Form/FormFactoryTest.php b/tests/Symfony/Tests/Component/Form/FormFactoryTest.php index e8361dfef3..6f36e5c4c0 100644 --- a/tests/Symfony/Tests/Component/Form/FormFactoryTest.php +++ b/tests/Symfony/Tests/Component/Form/FormFactoryTest.php @@ -492,7 +492,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase $this->setExpectedException('Symfony\Component\Form\Exception\CreationException', 'The options "invalid", "unknown" do not exist. Known options are: "data", "data_class", ' . - '"trim", "required", "read_only", "max_length", "pattern", "property_path", "by_reference", ' . + '"trim", "required", "read_only", "disabled", "max_length", "pattern", "property_path", "by_reference", ' . '"error_bubbling", "error_mapping", "label", "attr", "invalid_message", "invalid_message_parameters", ' . '"translation_domain", "empty_data"' ); @@ -507,7 +507,7 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase $this->setExpectedException('Symfony\Component\Form\Exception\CreationException', 'The option "unknown" does not exist. Known options are: "data", "data_class", ' . - '"trim", "required", "read_only", "max_length", "pattern", "property_path", "by_reference", ' . + '"trim", "required", "read_only", "disabled", "max_length", "pattern", "property_path", "by_reference", ' . '"error_bubbling", "error_mapping", "label", "attr", "invalid_message", "invalid_message_parameters", ' . '"translation_domain", "empty_data"' ); diff --git a/tests/Symfony/Tests/Component/Form/FormTest.php b/tests/Symfony/Tests/Component/Form/FormTest.php index 9975e0bed8..b0c7ae799d 100644 --- a/tests/Symfony/Tests/Component/Form/FormTest.php +++ b/tests/Symfony/Tests/Component/Form/FormTest.php @@ -156,10 +156,10 @@ class FormTest extends \PHPUnit_Framework_TestCase $this->form->bind(array()); } - public function testBindIsIgnoredIfReadOnly() + public function testBindIsIgnoredIfDisabled() { $form = $this->getBuilder() - ->setReadOnly(true) + ->setDisabled(true) ->setData('initial') ->getForm(); @@ -199,34 +199,34 @@ class FormTest extends \PHPUnit_Framework_TestCase $this->assertFalse($child->isRequired()); } - public function testAlwaysReadOnlyIfParentReadOnly() + public function testAlwaysDisabledIfParentDisabled() { - $parent = $this->getBuilder()->setReadOnly(true)->getForm(); - $child = $this->getBuilder()->setReadOnly(false)->getForm(); + $parent = $this->getBuilder()->setDisabled(true)->getForm(); + $child = $this->getBuilder()->setDisabled(false)->getForm(); $child->setParent($parent); - $this->assertTrue($child->isReadOnly()); + $this->assertTrue($child->isDisabled()); } - public function testReadOnly() + public function testDisabled() { - $parent = $this->getBuilder()->setReadOnly(false)->getForm(); - $child = $this->getBuilder()->setReadOnly(true)->getForm(); + $parent = $this->getBuilder()->setDisabled(false)->getForm(); + $child = $this->getBuilder()->setDisabled(true)->getForm(); $child->setParent($parent); - $this->assertTrue($child->isReadOnly()); + $this->assertTrue($child->isDisabled()); } - public function testNotReadOnly() + public function testNotDisabled() { - $parent = $this->getBuilder()->setReadOnly(false)->getForm(); - $child = $this->getBuilder()->setReadOnly(false)->getForm(); + $parent = $this->getBuilder()->setDisabled(false)->getForm(); + $child = $this->getBuilder()->setDisabled(false)->getForm(); $child->setParent($parent); - $this->assertFalse($child->isReadOnly()); + $this->assertFalse($child->isDisabled()); } public function testCloneChildren() @@ -305,15 +305,15 @@ class FormTest extends \PHPUnit_Framework_TestCase $this->assertTrue($this->form->isValid()); } - public function testValidIfBoundAndReadOnly() + public function testValidIfBoundAndDisabled() { - $form = $this->getBuilder()->setReadOnly(true)->getForm(); + $form = $this->getBuilder()->setDisabled(true)->getForm(); $form->bind('foobar'); $this->assertTrue($form->isValid()); } - public function testValidIfBoundAndReadOnlyWithChildren() + public function testValidIfBoundAndDisabledWithChildren() { $this->factory->expects($this->once()) ->method('createNamedBuilder') @@ -321,7 +321,7 @@ class FormTest extends \PHPUnit_Framework_TestCase ->will($this->returnValue($this->getBuilder('name'))); $form = $this->getBuilder('person') - ->setReadOnly(true) + ->setDisabled(true) ->add('name', 'text') ->getForm(); $form->bind(array('name' => 'Jacques Doe'));