Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 8657314

Browse filesBrowse files
feature #32747 [Form] Add "is empty callback" to form config (fancyweb)
This PR was merged into the 5.1-dev branch. Discussion ---------- [Form] Add "is empty callback" to form config | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #31572 for 4.4+ | License | MIT | Doc PR | - This PR introduces a new feature that allow to resolve a bug. Currently, the `isEmpty()` behavior of the `Form` class is the same whatever its configuration. That prevents us to specify a different behavior by form type. But I think that some form types should have dedicated empty values. For example, the `CheckboxType` model data either resolves to `true` (checked) or `false` (unchecked). But `false` is not an empty value in the `Form::isEmpty()` method, so a `CheckboxType` form can never be empty. `false` should not be in that list because for other form types, it's perfectly fine that it's not considered as an empty value. The problem is better seen in #31572 with a `ChoiceType` that is never considered as empty (when no radio button is checked). Being able to specify the "is empty" behavior by form type would also allow users to define their own logic in their custom form types + probably define it ourselves in all our form types in order to get rid of the default common behavior. Commits ------- 7bfc27e [Form] Add "is empty callback" to form config
2 parents 3bcf8cb + 7bfc27e commit 8657314
Copy full SHA for 8657314

16 files changed

+147Lines changed: 147 additions & 0 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎UPGRADE-5.1.md‎

Copy file name to clipboardExpand all lines: UPGRADE-5.1.md
+8Lines changed: 8 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ EventDispatcher
1616

1717
* Deprecated `LegacyEventDispatcherProxy`. Use the event dispatcher without the proxy.
1818

19+
Form
20+
----
21+
22+
* Implementing the `FormConfigInterface` without implementing the `getIsEmptyCallback()` method
23+
is deprecated. The method will be added to the interface in 6.0.
24+
* Implementing the `FormConfigBuilderInterface` without implementing the `setIsEmptyCallback()` method
25+
is deprecated. The method will be added to the interface in 6.0.
26+
1927
FrameworkBundle
2028
---------------
2129

Collapse file

‎UPGRADE-6.0.md‎

Copy file name to clipboardExpand all lines: UPGRADE-6.0.md
+6Lines changed: 6 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ EventDispatcher
1616

1717
* Removed `LegacyEventDispatcherProxy`. Use the event dispatcher without the proxy.
1818

19+
Form
20+
----
21+
22+
* Added the `getIsEmptyCallback()` method to the `FormConfigInterface`.
23+
* Added the `setIsEmptyCallback()` method to the `FormConfigBuilderInterface`.
24+
1925
FrameworkBundle
2026
---------------
2127

Collapse file

‎src/Symfony/Component/Form/ButtonBuilder.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/ButtonBuilder.php
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,16 @@ public function getFormConfig()
466466
return $config;
467467
}
468468

469+
/**
470+
* Unsupported method.
471+
*
472+
* @throws BadMethodCallException
473+
*/
474+
public function setIsEmptyCallback(?callable $isEmptyCallback)
475+
{
476+
throw new BadMethodCallException('Buttons do not support "is empty" callback.');
477+
}
478+
469479
/**
470480
* Unsupported method.
471481
*/
@@ -738,6 +748,16 @@ public function getOption(string $name, $default = null)
738748
return \array_key_exists($name, $this->options) ? $this->options[$name] : $default;
739749
}
740750

751+
/**
752+
* Unsupported method.
753+
*
754+
* @throws BadMethodCallException
755+
*/
756+
public function getIsEmptyCallback(): ?callable
757+
{
758+
throw new BadMethodCallException('Buttons do not support "is empty" callback.');
759+
}
760+
741761
/**
742762
* Unsupported method.
743763
*
Collapse file

‎src/Symfony/Component/Form/CHANGELOG.md‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/CHANGELOG.md
+4Lines changed: 4 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ CHANGELOG
66

77
* The `view_timezone` option defaults to the `model_timezone` if no `reference_date` is configured.
88
* Added default `inputmode` attribute to Search, Email and Tel form types.
9+
* Implementing the `FormConfigInterface` without implementing the `getIsEmptyCallback()` method
10+
is deprecated. The method will be added to the interface in 6.0.
11+
* Implementing the `FormConfigBuilderInterface` without implementing the `setIsEmptyCallback()` method
12+
is deprecated. The method will be added to the interface in 6.0.
913

1014
5.0.0
1115
-----
Collapse file

‎src/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Core/Type/CheckboxType.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public function configureOptions(OptionsResolver $resolver)
6060
'empty_data' => $emptyData,
6161
'compound' => false,
6262
'false_values' => [null],
63+
'is_empty_callback' => static function ($modelData): bool {
64+
return false === $modelData;
65+
},
6366
]);
6467

6568
$resolver->setAllowedTypes('false_values', 'array');
Collapse file

‎src/Symfony/Component/Form/Extension/Core/Type/FormType.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Core/Type/FormType.php
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
1616
use Symfony\Component\Form\Extension\Core\EventListener\TrimListener;
1717
use Symfony\Component\Form\FormBuilderInterface;
18+
use Symfony\Component\Form\FormConfigBuilderInterface;
1819
use Symfony\Component\Form\FormInterface;
1920
use Symfony\Component\Form\FormView;
2021
use Symfony\Component\OptionsResolver\Options;
@@ -58,6 +59,14 @@ public function buildForm(FormBuilderInterface $builder, array $options)
5859
if ($options['trim']) {
5960
$builder->addEventSubscriber(new TrimListener());
6061
}
62+
63+
if (!method_exists($builder, 'setIsEmptyCallback')) {
64+
@trigger_error(sprintf('Not implementing the "%s::setIsEmptyCallback()" method in "%s" is deprecated since Symfony 5.1.', FormConfigBuilderInterface::class, \get_class($builder)), E_USER_DEPRECATED);
65+
66+
return;
67+
}
68+
69+
$builder->setIsEmptyCallback($options['is_empty_callback']);
6170
}
6271

6372
/**
@@ -190,13 +199,15 @@ public function configureOptions(OptionsResolver $resolver)
190199
'help_attr' => [],
191200
'help_html' => false,
192201
'help_translation_parameters' => [],
202+
'is_empty_callback' => null,
193203
]);
194204

195205
$resolver->setAllowedTypes('label_attr', 'array');
196206
$resolver->setAllowedTypes('upload_max_size_message', ['callable']);
197207
$resolver->setAllowedTypes('help', ['string', 'null']);
198208
$resolver->setAllowedTypes('help_attr', 'array');
199209
$resolver->setAllowedTypes('help_html', 'bool');
210+
$resolver->setAllowedTypes('is_empty_callback', ['null', 'callable']);
200211
}
201212

202213
/**
Collapse file

‎src/Symfony/Component/Form/Form.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Form.php
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,18 @@ public function isEmpty()
726726
}
727727
}
728728

729+
if (!method_exists($this->config, 'getIsEmptyCallback')) {
730+
@trigger_error(sprintf('Not implementing the "%s::getIsEmptyCallback()" method in "%s" is deprecated since Symfony 5.1.', FormConfigInterface::class, \get_class($this->config)), E_USER_DEPRECATED);
731+
732+
$isEmptyCallback = null;
733+
} else {
734+
$isEmptyCallback = $this->config->getIsEmptyCallback();
735+
}
736+
737+
if (null !== $isEmptyCallback) {
738+
return $isEmptyCallback($this->modelData);
739+
}
740+
729741
return FormUtil::isEmpty($this->modelData) ||
730742
// arrays, countables
731743
((\is_array($this->modelData) || $this->modelData instanceof \Countable) && 0 === \count($this->modelData)) ||
Collapse file

‎src/Symfony/Component/Form/FormConfigBuilder.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/FormConfigBuilder.php
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface
102102

103103
private $autoInitialize = false;
104104
private $options;
105+
private $isEmptyCallback;
105106

106107
/**
107108
* Creates an empty form configuration.
@@ -461,6 +462,14 @@ public function getOption(string $name, $default = null)
461462
return \array_key_exists($name, $this->options) ? $this->options[$name] : $default;
462463
}
463464

465+
/**
466+
* {@inheritdoc}
467+
*/
468+
public function getIsEmptyCallback(): ?callable
469+
{
470+
return $this->isEmptyCallback;
471+
}
472+
464473
/**
465474
* {@inheritdoc}
466475
*/
@@ -761,6 +770,16 @@ public function getFormConfig()
761770
return $config;
762771
}
763772

773+
/**
774+
* {@inheritdoc}
775+
*/
776+
public function setIsEmptyCallback(?callable $isEmptyCallback)
777+
{
778+
$this->isEmptyCallback = $isEmptyCallback;
779+
780+
return $this;
781+
}
782+
764783
/**
765784
* Validates whether the given variable is a valid form name.
766785
*
Collapse file

‎src/Symfony/Component/Form/FormConfigBuilderInterface.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/FormConfigBuilderInterface.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
/**
1818
* @author Bernhard Schussek <bschussek@gmail.com>
19+
*
20+
* @method $this setIsEmptyCallback(callable|null $isEmptyCallback) Sets the callback that will be called to determine if the model data of the form is empty or not - not implementing it is deprecated since Symfony 5.1
1921
*/
2022
interface FormConfigBuilderInterface extends FormConfigInterface
2123
{
Collapse file

‎src/Symfony/Component/Form/FormConfigInterface.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/FormConfigInterface.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
* The configuration of a {@link Form} object.
1919
*
2020
* @author Bernhard Schussek <bschussek@gmail.com>
21+
*
22+
* @method callable|null getIsEmptyCallback() Returns a callable that takes the model data as argument and that returns if it is empty or not - not implementing it is deprecated since Symfony 5.1
2123
*/
2224
interface FormConfigInterface
2325
{

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.