Skip to content

Commit c2e7424

Browse files
committed
merged branch bschussek/issue5383 (PR #6528)
This PR was merged into the master branch. Discussion ---------- [2.3] [Form] Support buttons in forms Bug fix: no Feature addition: yes Backwards compatibility break: yes Symfony2 tests pass: yes Fixes the following tickets: #5383 Todo: - License of the code: MIT Documentation PR: symfony/symfony-docs#2489 The general idea of this PR is to be able to add buttons to forms like so: ```php $builder->add('clickme', 'submit'); ``` You can then check in the controller whether the button was clicked: ```php if ($form->get('clickme')->isClicked()) { // do stuff } ``` Button-specific validation groups are also supported: ```php $builder->add('clickme', 'submit', array( 'validation_groups' => 'OnlyClickMe', )); ``` The validation group will then override the one defined in the form if that button is clicked. This PR also introduces the disabling of form validation by passing the value `false` in the option `validation_groups`: ```php $builder->add('clickme', 'submit', array( 'validation_groups' => false, )); ``` The same can be achieved (already before this PR) by passing an empty array: ```php $builder->add('clickme', 'submit', array( 'validation_groups' => array(), )); ``` See the linked documentation for more information. Commits ------- faf8d7a [Form] Added upgrade information about setting "validation_groups" => false d504732 [Form] Added leading backslashes to @exceptionMessage doc blocks c8afa88 [Form] Removed deprecated code scheduled for removal in 2.3 36ca056 [Form] Simplified Twig code ce29c70 [Form] Fixed incorrect doc comment 0bc7129 [Form] Fixed invalid use of FormException 600007b [Form] The option "validation_groups" can now be set to false to disable validation. This is identical to setting it to an empty array. 277d6df [Form] Fixed concatenation operator CS (see 7c47e34928c39e4797edc841423237a16588395e) 7b07925 [Form] Changed isset() to array_key_exists() to be consistent with ParameterBag 7b438a8 [Form] Made submit buttons able to convey validation groups cc2118d [Form] Implemented support for buttons
2 parents dda390a + 667bbe4 commit c2e7424

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2281
-374
lines changed

Button.php

Lines changed: 412 additions & 0 deletions
Large diffs are not rendered by default.

ButtonBuilder.php

Lines changed: 750 additions & 0 deletions
Large diffs are not rendered by default.

ButtonTypeInterface.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form;
13+
14+
/**
15+
* A type that should be converted into a {@link Button} instance.
16+
*
17+
* @author Bernhard Schussek <bschussek@gmail.com>
18+
*/
19+
interface ButtonTypeInterface extends FormTypeInterface
20+
{
21+
}

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ CHANGELOG
2828
* added an optional PropertyAccessorInterface parameter to FormType,
2929
ObjectChoiceList and PropertyPathMapper
3030
* [BC BREAK] PropertyPathMapper and FormType now have a constructor
31+
* [BC BREAK] setting the option "validation_groups" to ``false`` now disables validation
32+
instead of assuming group "Default"
3133

3234
2.1.0
3335
-----

ClickableInterface.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form;
13+
14+
/**
15+
* A clickable form element.
16+
*
17+
* @author Bernhard Schussek <bschussek@gmail.com>
18+
*/
19+
interface ClickableInterface
20+
{
21+
/**
22+
* Returns whether this element was clicked.
23+
*
24+
* @return Boolean Whether this element was clicked.
25+
*/
26+
public function isClicked();
27+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Exception;
13+
14+
/**
15+
* Base InvalidArgumentException for the Form component.
16+
*
17+
* @author Bernhard Schussek <bschussek@gmail.com>
18+
*/
19+
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
20+
{
21+
}

Extension/Core/CoreExtension.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ protected function loadTypes()
5050
new Type\TimezoneType(),
5151
new Type\UrlType(),
5252
new Type\FileType(),
53+
new Type\ButtonType(),
54+
new Type\SubmitType(),
55+
new Type\ResetType(),
5356
);
5457
}
5558
}

Extension/Core/Type/BaseType.php

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Extension\Core\Type;
13+
14+
use Symfony\Component\Form\AbstractType;
15+
use Symfony\Component\Form\FormBuilderInterface;
16+
use Symfony\Component\Form\FormInterface;
17+
use Symfony\Component\Form\FormView;
18+
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
19+
20+
/**
21+
* Encapsulates common logic of {@link FormType} and {@link ButtonType}.
22+
*
23+
* This type does not appear in the form's type inheritance chain and as such
24+
* cannot be extended (via {@link FormTypeExtension}s) nor themed.
25+
*
26+
* @author Bernhard Schussek <bschussek@gmail.com>
27+
*/
28+
abstract class BaseType extends AbstractType
29+
{
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function buildForm(FormBuilderInterface $builder, array $options)
34+
{
35+
$builder->setDisabled($options['disabled']);
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public function buildView(FormView $view, FormInterface $form, array $options)
42+
{
43+
$name = $form->getName();
44+
$blockName = $options['block_name'] ?: $form->getName();
45+
$translationDomain = $options['translation_domain'];
46+
47+
if ($view->parent) {
48+
if ('' !== ($parentFullName = $view->parent->vars['full_name'])) {
49+
$id = sprintf('%s_%s', $view->parent->vars['id'], $name);
50+
$fullName = sprintf('%s[%s]', $parentFullName, $name);
51+
$uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName);
52+
} else {
53+
$id = $name;
54+
$fullName = $name;
55+
$uniqueBlockPrefix = '_'.$blockName;
56+
}
57+
58+
if (!$translationDomain) {
59+
$translationDomain = $view->parent->vars['translation_domain'];
60+
}
61+
} else {
62+
$id = $name;
63+
$fullName = $name;
64+
$uniqueBlockPrefix = '_'.$blockName;
65+
66+
// Strip leading underscores and digits. These are allowed in
67+
// form names, but not in HTML4 ID attributes.
68+
// http://www.w3.org/TR/html401/struct/global.html#adef-id
69+
$id = ltrim($id, '_0123456789');
70+
}
71+
72+
$blockPrefixes = array();
73+
for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) {
74+
array_unshift($blockPrefixes, $type->getName());
75+
}
76+
$blockPrefixes[] = $uniqueBlockPrefix;
77+
78+
if (!$translationDomain) {
79+
$translationDomain = 'messages';
80+
}
81+
82+
$view->vars = array_replace($view->vars, array(
83+
'form' => $view,
84+
'id' => $id,
85+
'name' => $name,
86+
'full_name' => $fullName,
87+
'disabled' => $form->isDisabled(),
88+
'label' => $options['label'],
89+
'multipart' => false,
90+
'attr' => $options['attr'],
91+
'block_prefixes' => $blockPrefixes,
92+
'unique_block_prefix' => $uniqueBlockPrefix,
93+
'translation_domain' => $translationDomain,
94+
// Using the block name here speeds up performance in collection
95+
// forms, where each entry has the same full block name.
96+
// Including the type is important too, because if rows of a
97+
// collection form have different types (dynamically), they should
98+
// be rendered differently.
99+
// https://github.com/symfony/symfony/issues/5038
100+
'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(),
101+
));
102+
}
103+
104+
/**
105+
* {@inheritdoc}
106+
*/
107+
public function setDefaultOptions(OptionsResolverInterface $resolver)
108+
{
109+
$resolver->setDefaults(array(
110+
'block_name' => null,
111+
'disabled' => false,
112+
'label' => null,
113+
'attr' => array(),
114+
'translation_domain' => null,
115+
));
116+
117+
$resolver->setAllowedTypes(array(
118+
'attr' => 'array',
119+
));
120+
}
121+
}

Extension/Core/Type/ButtonType.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Extension\Core\Type;
13+
14+
use Symfony\Component\Form\ButtonTypeInterface;
15+
16+
/**
17+
* A form button.
18+
*
19+
* @author Bernhard Schussek <bschussek@gmail.com>
20+
*/
21+
class ButtonType extends BaseType implements ButtonTypeInterface
22+
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
public function getParent()
27+
{
28+
return null;
29+
}
30+
31+
/**
32+
* {@inheritdoc}
33+
*/
34+
public function getName()
35+
{
36+
return 'button';
37+
}
38+
}

0 commit comments

Comments
 (0)